Adding untested message tribute contract

This commit is contained in:
Richard Ramos 2018-03-16 15:11:20 -04:00
parent 4d862684ea
commit 09f39106d4
1 changed files with 124 additions and 53 deletions

View File

@ -1,68 +1,139 @@
pragma solidity ^0.4.17;
import "../common/Controlled.sol";
import "../token/MiniMeToken.sol";
/*
Inspired by one of Satoshi Nakamotos original suggested use cases for Bitcoin,
we will be introducing an economics-based anti-spam filter, in our case for
receiving messages and cold contact requests from users.
SNT is deposited, and transferred from stakeholders to recipients upon receiving
a reply from the recipient.
/**
* @title MessageTribute
* @author Richard Ramos (Status Research & Development GmbH)
* @dev Inspired by one of Satoshi Nakamotos original suggested use cases for Bitcoin,
we will be introducing an economics-based anti-spam filter, in our case for
receiving messages and cold contact requests from users.
SNT is deposited, and transferred from stakeholders to recipients upon receiving
a reply from the recipient.
*/
contract MessageTribute is Controlled {
// Uses:
MiniMeToken public SNT;
/*
// B will request 100SNT from everyone for messages
feeCatalog[B_ADDRESS][address(0)] = 100
*/
/*
// A wants to send a message to B
// B requires that A pays 100SNT
feeCatalog[B_ADDRESS][A_ADDRESS] = 100;
---------------------------------------
// A will check if B has a fee set up
bool hasFee = feeCatalog[B_ADDRESS][address(0)] > 0 || feeCatalog[B_ADDRESS][A_ADDRESS] > 0
if(hasFee){
uint256 fee = feeCatalog[B_ADDRESS][address(0)];
if(feeCatalog[B_ADDRESS][A_ADDRESS] > fee)
fee = feeCatalog[B_ADDRESS][A_ADDRESS];
}
---------------------------------------
A will pay or decide to not send the message
---------------------------------------
// B wants a non permanent fee for A
// After he pays for the first message,
// All following messages will be free
permanentFee[B_ADDRESS][A_ADDRESS] = false;
Then after applying fee, we should set:
feeCatalog[B_ADDRESS][A_ADDRESS] = 0;
---------------------------------------
// B wants a permanent fee for A
permanentFee[B_ADDRESS][A_ADDRESS] = true;
*/
contract MessageTribute {
struct Request {
address from;
address to;
uint256 timestamp;
struct Fee {
uint256 amount;
bool tribute;
bool permanent;
}
mapping(address => mapping(address => uint256)) feeCatalog;
mapping(address => mapping(address => bool)) permanentFee;
mapping(address => mapping(address => Fee)) feeCatalog;
mapping(address => uint256) balances;
function MessageTribute() public {
struct Audience {
uint256 blockNum;
Fee fee;
}
mapping(address => mapping(address => Audience)) audienceRequested;
function MessageTribute(address _SNT) public {
SNT = MiniMeToken(_SNT);
}
function setRequiredTribute(address _to, uint _amount, bool _isTribute, bool _isPermanent) public {
feeCatalog[msg.sender][_to] = Fee(_amount, _isTribute, _isPermanent);
}
function getRequiredFee(address _from) public view
returns (uint256 fee, bool tribute)
{
Fee memory f = getFee(_from);
fee = f.amount;
tribute = f.tribute;
}
function getFee(address _from) internal
returns (Fee)
{
Fee memory generalFee = feeCatalog[_from][address(0)];
Fee memory specificFee = feeCatalog[_from][msg.sender];
return specificFee.amount > 0 ? specificFee : generalFee;
}
function deposit(uint256 _value) public {
require(_value > 0);
balances[msg.sender] += _value;
require(SNT.transferFrom(msg.sender, this, _value));
}
function balance() public view returns (uint256) {
return balances[msg.sender];
}
function widthdraw(uint256 _value) public {
require(balances[msg.sender] > 0);
require(_value <= balances[msg.sender]);
require(SNT.transferFrom(msg.sender, this, _value));
}
event AudienceRequested(address from, address to);
event AudienceCancelled(address from, address to);
event AudienceGranted(address from, address to, bool approve);
function requestAudience(address _from)
public
{
Fee memory f = getFee(_from);
require(f.amount <= balances[msg.sender]);
AudienceRequested(_from, msg.sender);
audienceRequested[_from][msg.sender] = Audience(block.number, f);
balances[msg.sender] -= f.amount;
}
function cancelAudienceRequest(address _from) public {
if (audienceRequested[_from][msg.sender].blockNum > 0) {
AudienceCancelled(_from, msg.sender);
balances[msg.sender] += audienceRequested[_from][msg.sender].fee.amount;
delete audienceRequested[_from][msg.sender];
}
}
function grantAudience(address _to, bool _approve) {
Audience memory aud = audienceRequested[msg.sender][_to];
require(aud.blockNum > 0);
AudienceGranted(msg.sender, _to, _approve);
bool isTribute = aud.fee.tribute;
uint256 amount = aud.fee.amount;
delete audienceRequested[msg.sender][_to];
clearFee(msg.sender, _to);
if (isTribute) {
if (_approve) {
require(SNT.transferFrom(this, msg.sender, amount));
} else {
balances[_to] += amount;
}
}
}
function hasEnoughFundsToTalk(address _to)
public
view
returns(bool)
{
return getFee(_to).amount <= balances[msg.sender];
}
function clearFee(address _from, address _to) private {
if (!feeCatalog[_from][_to].permanent) {
feeCatalog[_from][_to].amount = 0;
feeCatalog[_from][_to].tribute = false;
feeCatalog[_from][_to].permanent = false;
}
}
}