From 09f39106d4ccd51d13073ab94a40d7e99c866b3f Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Fri, 16 Mar 2018 15:11:20 -0400 Subject: [PATCH] Adding untested message tribute contract --- contracts/communication/MessageTribute.sol | 177 +++++++++++++++------ 1 file changed, 124 insertions(+), 53 deletions(-) diff --git a/contracts/communication/MessageTribute.sol b/contracts/communication/MessageTribute.sol index fbdbca2..6998ecf 100644 --- a/contracts/communication/MessageTribute.sol +++ b/contracts/communication/MessageTribute.sol @@ -1,68 +1,139 @@ pragma solidity ^0.4.17; +import "../common/Controlled.sol"; +import "../token/MiniMeToken.sol"; -/* -Inspired by one of Satoshi Nakamoto’s 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 Nakamoto’s 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; - - function MessageTribute() public { + mapping(address => mapping(address => Fee)) feeCatalog; + mapping(address => uint256) balances; + 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; + } + } }