More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 886 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Propose Contribu... | 16574371 | 537 days ago | IN | 0 ETH | 0.01134037 | ||||
Propose Contribu... | 16534324 | 543 days ago | IN | 0 ETH | 0.00842401 | ||||
Propose Contribu... | 16533937 | 543 days ago | IN | 0 ETH | 0.00854523 | ||||
Propose Contribu... | 16512504 | 546 days ago | IN | 0 ETH | 0.01702561 | ||||
Propose Contribu... | 16484594 | 550 days ago | IN | 0 ETH | 0.00931655 | ||||
Propose Contribu... | 16484576 | 550 days ago | IN | 0 ETH | 0.00705011 | ||||
Propose Contribu... | 16475968 | 551 days ago | IN | 0 ETH | 0.00649689 | ||||
Propose Contribu... | 16454724 | 554 days ago | IN | 0 ETH | 0.00744959 | ||||
Propose Contribu... | 16390104 | 563 days ago | IN | 0 ETH | 0.0062415 | ||||
Propose Contribu... | 16388641 | 563 days ago | IN | 0 ETH | 0.00679945 | ||||
Propose Contribu... | 16370085 | 566 days ago | IN | 0 ETH | 0.00884381 | ||||
Propose Contribu... | 16370075 | 566 days ago | IN | 0 ETH | 0.00904935 | ||||
Propose Contribu... | 16367544 | 566 days ago | IN | 0 ETH | 0.00669925 | ||||
Propose Contribu... | 16367522 | 566 days ago | IN | 0 ETH | 0.0069377 | ||||
Propose Contribu... | 16351193 | 568 days ago | IN | 0 ETH | 0.00820411 | ||||
Propose Contribu... | 16347757 | 569 days ago | IN | 0 ETH | 0.00847156 | ||||
Propose Contribu... | 16333711 | 571 days ago | IN | 0 ETH | 0.00645972 | ||||
Propose Contribu... | 16319241 | 573 days ago | IN | 0 ETH | 0.00615178 | ||||
Propose Contribu... | 16317899 | 573 days ago | IN | 0 ETH | 0.00891292 | ||||
Propose Contribu... | 16247345 | 583 days ago | IN | 0 ETH | 0.00573104 | ||||
Propose Contribu... | 16240989 | 584 days ago | IN | 0 ETH | 0.00716085 | ||||
Propose Contribu... | 16240978 | 584 days ago | IN | 0 ETH | 0.00716186 | ||||
Propose Contribu... | 16240959 | 584 days ago | IN | 0 ETH | 0.00855009 | ||||
Propose Contribu... | 16236108 | 585 days ago | IN | 0 ETH | 0.00513912 | ||||
Propose Contribu... | 16236083 | 585 days ago | IN | 0 ETH | 0.00567048 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ContributionReward
Compiler Version
v0.5.4+commit.9549d8ff
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2019-05-27 */ // File: @daostack/infra/contracts/votingMachines/IntVoteInterface.sol pragma solidity ^0.5.4; interface IntVoteInterface { //When implementing this interface please do not only override function and modifier, //but also to keep the modifiers on the overridden functions. modifier onlyProposalOwner(bytes32 _proposalId) {revert(); _;} modifier votable(bytes32 _proposalId) {revert(); _;} event NewProposal( bytes32 indexed _proposalId, address indexed _organization, uint256 _numOfChoices, address _proposer, bytes32 _paramsHash ); event ExecuteProposal(bytes32 indexed _proposalId, address indexed _organization, uint256 _decision, uint256 _totalReputation ); event VoteProposal( bytes32 indexed _proposalId, address indexed _organization, address indexed _voter, uint256 _vote, uint256 _reputation ); event CancelProposal(bytes32 indexed _proposalId, address indexed _organization ); event CancelVoting(bytes32 indexed _proposalId, address indexed _organization, address indexed _voter); /** * @dev register a new proposal with the given parameters. Every proposal has a unique ID which is being * generated by calculating keccak256 of a incremented counter. * @param _numOfChoices number of voting choices * @param _proposalParameters defines the parameters of the voting machine used for this proposal * @param _proposer address * @param _organization address - if this address is zero the msg.sender will be used as the organization address. * @return proposal's id. */ function propose( uint256 _numOfChoices, bytes32 _proposalParameters, address _proposer, address _organization ) external returns(bytes32); function vote( bytes32 _proposalId, uint256 _vote, uint256 _rep, address _voter ) external returns(bool); function cancelVote(bytes32 _proposalId) external; function getNumberOfChoices(bytes32 _proposalId) external view returns(uint256); function isVotable(bytes32 _proposalId) external view returns(bool); /** * @dev voteStatus returns the reputation voted for a proposal for a specific voting choice. * @param _proposalId the ID of the proposal * @param _choice the index in the * @return voted reputation for the given choice */ function voteStatus(bytes32 _proposalId, uint256 _choice) external view returns(uint256); /** * @dev isAbstainAllow returns if the voting machine allow abstain (0) * @return bool true or false */ function isAbstainAllow() external pure returns(bool); /** * @dev getAllowedRangeOfChoices returns the allowed range of choices for a voting machine. * @return min - minimum number of choices max - maximum number of choices */ function getAllowedRangeOfChoices() external pure returns(uint256 min, uint256 max); } // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ interface IERC20 { function transfer(address to, uint256 value) external returns (bool); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function totalSupply() external view returns (uint256); function balanceOf(address who) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } // File: @daostack/infra/contracts/votingMachines/VotingMachineCallbacksInterface.sol pragma solidity ^0.5.4; interface VotingMachineCallbacksInterface { function mintReputation(uint256 _amount, address _beneficiary, bytes32 _proposalId) external returns(bool); function burnReputation(uint256 _amount, address _owner, bytes32 _proposalId) external returns(bool); function stakingTokenTransfer(IERC20 _stakingToken, address _beneficiary, uint256 _amount, bytes32 _proposalId) external returns(bool); function getTotalReputationSupply(bytes32 _proposalId) external view returns(uint256); function reputationOf(address _owner, bytes32 _proposalId) external view returns(uint256); function balanceOfStakingToken(IERC20 _stakingToken, bytes32 _proposalId) external view returns(uint256); } // File: openzeppelin-solidity/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ constructor () internal { _owner = msg.sender; emit OwnershipTransferred(address(0), _owner); } /** * @return the address of the owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Allows the current owner to relinquish control of the contract. * @notice Renouncing to ownership will leave the contract without an owner. * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: @daostack/infra/contracts/Reputation.sol pragma solidity ^0.5.4; /** * @title Reputation system * @dev A DAO has Reputation System which allows peers to rate other peers in order to build trust . * A reputation is use to assign influence measure to a DAO'S peers. * Reputation is similar to regular tokens but with one crucial difference: It is non-transferable. * The Reputation contract maintain a map of address to reputation value. * It provides an onlyOwner functions to mint and burn reputation _to (or _from) a specific address. */ contract Reputation is Ownable { uint8 public decimals = 18; //Number of decimals of the smallest unit // Event indicating minting of reputation to an address. event Mint(address indexed _to, uint256 _amount); // Event indicating burning of reputation for an address. event Burn(address indexed _from, uint256 _amount); /// @dev `Checkpoint` is the structure that attaches a block number to a /// given value, the block number attached is the one that last changed the /// value struct Checkpoint { // `fromBlock` is the block number that the value was generated from uint128 fromBlock; // `value` is the amount of reputation at a specific block number uint128 value; } // `balances` is the map that tracks the balance of each address, in this // contract when the balance changes the block number that the change // occurred is also included in the map mapping (address => Checkpoint[]) balances; // Tracks the history of the `totalSupply` of the reputation Checkpoint[] totalSupplyHistory; /// @notice Constructor to create a Reputation constructor( ) public { } /// @dev This function makes it easy to get the total number of reputation /// @return The total number of reputation function totalSupply() public view returns (uint256) { return totalSupplyAt(block.number); } //////////////// // Query balance and totalSupply in History //////////////// /** * @dev return the reputation amount of a given owner * @param _owner an address of the owner which we want to get his reputation */ function balanceOf(address _owner) public view returns (uint256 balance) { return balanceOfAt(_owner, block.number); } /// @dev Queries the balance of `_owner` at a specific `_blockNumber` /// @param _owner The address from which the balance will be retrieved /// @param _blockNumber The block number when the balance is queried /// @return The balance at `_blockNumber` function balanceOfAt(address _owner, uint256 _blockNumber) public view returns (uint256) { if ((balances[_owner].length == 0) || (balances[_owner][0].fromBlock > _blockNumber)) { return 0; // This will return the expected balance during normal situations } else { return getValueAt(balances[_owner], _blockNumber); } } /// @notice Total amount of reputation at a specific `_blockNumber`. /// @param _blockNumber The block number when the totalSupply is queried /// @return The total amount of reputation at `_blockNumber` function totalSupplyAt(uint256 _blockNumber) public view returns(uint256) { if ((totalSupplyHistory.length == 0) || (totalSupplyHistory[0].fromBlock > _blockNumber)) { return 0; // This will return the expected totalSupply during normal situations } else { return getValueAt(totalSupplyHistory, _blockNumber); } } /// @notice Generates `_amount` reputation that are assigned to `_owner` /// @param _user The address that will be assigned the new reputation /// @param _amount The quantity of reputation generated /// @return True if the reputation are generated correctly function mint(address _user, uint256 _amount) public onlyOwner returns (bool) { uint256 curTotalSupply = totalSupply(); require(curTotalSupply + _amount >= curTotalSupply); // Check for overflow uint256 previousBalanceTo = balanceOf(_user); require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount); updateValueAtNow(balances[_user], previousBalanceTo + _amount); emit Mint(_user, _amount); return true; } /// @notice Burns `_amount` reputation from `_owner` /// @param _user The address that will lose the reputation /// @param _amount The quantity of reputation to burn /// @return True if the reputation are burned correctly function burn(address _user, uint256 _amount) public onlyOwner returns (bool) { uint256 curTotalSupply = totalSupply(); uint256 amountBurned = _amount; uint256 previousBalanceFrom = balanceOf(_user); if (previousBalanceFrom < amountBurned) { amountBurned = previousBalanceFrom; } updateValueAtNow(totalSupplyHistory, curTotalSupply - amountBurned); updateValueAtNow(balances[_user], previousBalanceFrom - amountBurned); emit Burn(_user, amountBurned); return true; } //////////////// // Internal helper functions to query and set a value in a snapshot array //////////////// /// @dev `getValueAt` retrieves the number of reputation at a given block number /// @param checkpoints The history of values being queried /// @param _block The block number to retrieve the value at /// @return The number of reputation being queried function getValueAt(Checkpoint[] storage checkpoints, uint256 _block) internal view returns (uint256) { if (checkpoints.length == 0) { return 0; } // Shortcut for the actual value if (_block >= checkpoints[checkpoints.length-1].fromBlock) { return checkpoints[checkpoints.length-1].value; } if (_block < checkpoints[0].fromBlock) { return 0; } // Binary search of the value in the array uint256 min = 0; uint256 max = checkpoints.length-1; while (max > min) { uint256 mid = (max + min + 1) / 2; if (checkpoints[mid].fromBlock<=_block) { min = mid; } else { max = mid-1; } } return checkpoints[min].value; } /// @dev `updateValueAtNow` used to update the `balances` map and the /// `totalSupplyHistory` /// @param checkpoints The history of data being updated /// @param _value The new number of reputation function updateValueAtNow(Checkpoint[] storage checkpoints, uint256 _value) internal { require(uint128(_value) == _value); //check value is in the 128 bits bounderies if ((checkpoints.length == 0) || (checkpoints[checkpoints.length - 1].fromBlock < block.number)) { Checkpoint storage newCheckPoint = checkpoints[checkpoints.length++]; newCheckPoint.fromBlock = uint128(block.number); newCheckPoint.value = uint128(_value); } else { Checkpoint storage oldCheckPoint = checkpoints[checkpoints.length-1]; oldCheckPoint.value = uint128(_value); } } } // File: openzeppelin-solidity/contracts/math/SafeMath.sol pragma solidity ^0.5.0; /** * @title SafeMath * @dev Unsigned math operations with safety checks that revert on error */ library SafeMath { /** * @dev Multiplies two unsigned integers, reverts on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b); return c; } /** * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); uint256 c = a - b; return c; } /** * @dev Adds two unsigned integers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); return c; } /** * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0); return a % b; } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.0; /** * @title Standard ERC20 token * * @dev Implementation of the basic standard token. * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md * Originally based on code by FirstBlood: * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol * * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for * all accounts just by listening to said events. Note that this isn't required by the specification, and other * compliant implementations may not do it. */ contract ERC20 is IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowed; uint256 private _totalSupply; /** * @dev Total number of tokens in existence */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev Gets the balance of the specified address. * @param owner The address to query the balance of. * @return An uint256 representing the amount owned by the passed address. */ function balanceOf(address owner) public view returns (uint256) { return _balances[owner]; } /** * @dev Function to check the amount of tokens that an owner allowed to a spender. * @param owner address The address which owns the funds. * @param spender address The address which will spend the funds. * @return A uint256 specifying the amount of tokens still available for the spender. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowed[owner][spender]; } /** * @dev Transfer token for a specified address * @param to The address to transfer to. * @param value The amount to be transferred. */ function transfer(address to, uint256 value) public returns (bool) { _transfer(msg.sender, to, value); return true; } /** * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. * Beware that changing an allowance with this method brings the risk that someone may use both the old * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. */ function approve(address spender, uint256 value) public returns (bool) { require(spender != address(0)); _allowed[msg.sender][spender] = value; emit Approval(msg.sender, spender, value); return true; } /** * @dev Transfer tokens from one address to another. * Note that while this function emits an Approval event, this is not required as per the specification, * and other compliant implementations may not emit the event. * @param from address The address which you want to send tokens from * @param to address The address which you want to transfer to * @param value uint256 the amount of tokens to be transferred */ function transferFrom(address from, address to, uint256 value) public returns (bool) { _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); _transfer(from, to, value); emit Approval(from, msg.sender, _allowed[from][msg.sender]); return true; } /** * @dev Increase the amount of tokens that an owner allowed to a spender. * approve should be called when allowed_[_spender] == 0. To increment * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * Emits an Approval event. * @param spender The address which will spend the funds. * @param addedValue The amount of tokens to increase the allowance by. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { require(spender != address(0)); _allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue); emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); return true; } /** * @dev Decrease the amount of tokens that an owner allowed to a spender. * approve should be called when allowed_[_spender] == 0. To decrement * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * Emits an Approval event. * @param spender The address which will spend the funds. * @param subtractedValue The amount of tokens to decrease the allowance by. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { require(spender != address(0)); _allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue); emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); return true; } /** * @dev Transfer token for a specified addresses * @param from The address to transfer from. * @param to The address to transfer to. * @param value The amount to be transferred. */ function _transfer(address from, address to, uint256 value) internal { require(to != address(0)); _balances[from] = _balances[from].sub(value); _balances[to] = _balances[to].add(value); emit Transfer(from, to, value); } /** * @dev Internal function that mints an amount of the token and assigns it to * an account. This encapsulates the modification of balances such that the * proper events are emitted. * @param account The account that will receive the created tokens. * @param value The amount that will be created. */ function _mint(address account, uint256 value) internal { require(account != address(0)); _totalSupply = _totalSupply.add(value); _balances[account] = _balances[account].add(value); emit Transfer(address(0), account, value); } /** * @dev Internal function that burns an amount of the token of a given * account. * @param account The account whose tokens will be burnt. * @param value The amount that will be burnt. */ function _burn(address account, uint256 value) internal { require(account != address(0)); _totalSupply = _totalSupply.sub(value); _balances[account] = _balances[account].sub(value); emit Transfer(account, address(0), value); } /** * @dev Internal function that burns an amount of the token of a given * account, deducting from the sender's allowance for said account. Uses the * internal burn function. * Emits an Approval event (reflecting the reduced allowance). * @param account The account whose tokens will be burnt. * @param value The amount that will be burnt. */ function _burnFrom(address account, uint256 value) internal { _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(value); _burn(account, value); emit Approval(account, msg.sender, _allowed[account][msg.sender]); } } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol pragma solidity ^0.5.0; /** * @title Burnable Token * @dev Token that can be irreversibly burned (destroyed). */ contract ERC20Burnable is ERC20 { /** * @dev Burns a specific amount of tokens. * @param value The amount of token to be burned. */ function burn(uint256 value) public { _burn(msg.sender, value); } /** * @dev Burns a specific amount of tokens from the target address and decrements allowance * @param from address The address which you want to send tokens from * @param value uint256 The amount of token to be burned */ function burnFrom(address from, uint256 value) public { _burnFrom(from, value); } } // File: contracts/controller/DAOToken.sol pragma solidity ^0.5.4; /** * @title DAOToken, base on zeppelin contract. * @dev ERC20 compatible token. It is a mintable, burnable token. */ contract DAOToken is ERC20, ERC20Burnable, Ownable { string public name; string public symbol; // solhint-disable-next-line const-name-snakecase uint8 public constant decimals = 18; uint256 public cap; /** * @dev Constructor * @param _name - token name * @param _symbol - token symbol * @param _cap - token cap - 0 value means no cap */ constructor(string memory _name, string memory _symbol, uint256 _cap) public { name = _name; symbol = _symbol; cap = _cap; } /** * @dev Function to mint tokens * @param _to The address that will receive the minted tokens. * @param _amount The amount of tokens to mint. */ function mint(address _to, uint256 _amount) public onlyOwner returns (bool) { if (cap > 0) require(totalSupply().add(_amount) <= cap); _mint(_to, _amount); return true; } } // File: openzeppelin-solidity/contracts/utils/Address.sol pragma solidity ^0.5.0; /** * Utility library of inline functions on addresses */ library Address { /** * Returns whether the target address is a contract * @dev This function will return false if invoked during the constructor of a contract, * as the code is not actually created until after the constructor finishes. * @param account address of the account to check * @return whether the target address is a contract */ function isContract(address account) internal view returns (bool) { uint256 size; // XXX Currently there is no better way to check if there is a contract in an address // than to check the size of the code at that address. // See https://ethereum.stackexchange.com/a/14016/36603 // for more details about how this works. // TODO Check this again before the Serenity release, because all addresses will be // contracts then. // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } } // File: contracts/libs/SafeERC20.sol /* SafeERC20 by daostack. The code is based on a fix by SECBIT Team. USE WITH CAUTION & NO WARRANTY REFERENCE & RELATED READING - https://github.com/ethereum/solidity/issues/4116 - https://medium.com/@chris_77367/explaining-unexpected-reverts-starting-with-solidity-0-4-22-3ada6e82308c - https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca - https://gist.github.com/BrendanChou/88a2eeb80947ff00bcf58ffdafeaeb61 */ pragma solidity ^0.5.4; library SafeERC20 { using Address for address; bytes4 constant private TRANSFER_SELECTOR = bytes4(keccak256(bytes("transfer(address,uint256)"))); bytes4 constant private TRANSFERFROM_SELECTOR = bytes4(keccak256(bytes("transferFrom(address,address,uint256)"))); bytes4 constant private APPROVE_SELECTOR = bytes4(keccak256(bytes("approve(address,uint256)"))); function safeTransfer(address _erc20Addr, address _to, uint256 _value) internal { // Must be a contract addr first! require(_erc20Addr.isContract()); (bool success, bytes memory returnValue) = // solhint-disable-next-line avoid-low-level-calls _erc20Addr.call(abi.encodeWithSelector(TRANSFER_SELECTOR, _to, _value)); // call return false when something wrong require(success); //check return value require(returnValue.length == 0 || (returnValue.length == 32 && (returnValue[31] != 0))); } function safeTransferFrom(address _erc20Addr, address _from, address _to, uint256 _value) internal { // Must be a contract addr first! require(_erc20Addr.isContract()); (bool success, bytes memory returnValue) = // solhint-disable-next-line avoid-low-level-calls _erc20Addr.call(abi.encodeWithSelector(TRANSFERFROM_SELECTOR, _from, _to, _value)); // call return false when something wrong require(success); //check return value require(returnValue.length == 0 || (returnValue.length == 32 && (returnValue[31] != 0))); } function safeApprove(address _erc20Addr, address _spender, uint256 _value) internal { // Must be a contract addr first! require(_erc20Addr.isContract()); // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. require((_value == 0) || (IERC20(_erc20Addr).allowance(address(this), _spender) == 0)); (bool success, bytes memory returnValue) = // solhint-disable-next-line avoid-low-level-calls _erc20Addr.call(abi.encodeWithSelector(APPROVE_SELECTOR, _spender, _value)); // call return false when something wrong require(success); //check return value require(returnValue.length == 0 || (returnValue.length == 32 && (returnValue[31] != 0))); } } // File: contracts/controller/Avatar.sol pragma solidity ^0.5.4; /** * @title An Avatar holds tokens, reputation and ether for a controller */ contract Avatar is Ownable { using SafeERC20 for address; string public orgName; DAOToken public nativeToken; Reputation public nativeReputation; event GenericCall(address indexed _contract, bytes _data, uint _value, bool _success); event SendEther(uint256 _amountInWei, address indexed _to); event ExternalTokenTransfer(address indexed _externalToken, address indexed _to, uint256 _value); event ExternalTokenTransferFrom(address indexed _externalToken, address _from, address _to, uint256 _value); event ExternalTokenApproval(address indexed _externalToken, address _spender, uint256 _value); event ReceiveEther(address indexed _sender, uint256 _value); event MetaData(string _metaData); /** * @dev the constructor takes organization name, native token and reputation system and creates an avatar for a controller */ constructor(string memory _orgName, DAOToken _nativeToken, Reputation _nativeReputation) public { orgName = _orgName; nativeToken = _nativeToken; nativeReputation = _nativeReputation; } /** * @dev enables an avatar to receive ethers */ function() external payable { emit ReceiveEther(msg.sender, msg.value); } /** * @dev perform a generic call to an arbitrary contract * @param _contract the contract's address to call * @param _data ABI-encoded contract call to call `_contract` address. * @param _value value (ETH) to transfer with the transaction * @return bool success or fail * bytes - the return bytes of the called contract's function. */ function genericCall(address _contract, bytes memory _data, uint256 _value) public onlyOwner returns(bool success, bytes memory returnValue) { // solhint-disable-next-line avoid-call-value (success, returnValue) = _contract.call.value(_value)(_data); emit GenericCall(_contract, _data, _value, success); } /** * @dev send ethers from the avatar's wallet * @param _amountInWei amount to send in Wei units * @param _to send the ethers to this address * @return bool which represents success */ function sendEther(uint256 _amountInWei, address payable _to) public onlyOwner returns(bool) { _to.transfer(_amountInWei); emit SendEther(_amountInWei, _to); return true; } /** * @dev external token transfer * @param _externalToken the token contract * @param _to the destination address * @param _value the amount of tokens to transfer * @return bool which represents success */ function externalTokenTransfer(IERC20 _externalToken, address _to, uint256 _value) public onlyOwner returns(bool) { address(_externalToken).safeTransfer(_to, _value); emit ExternalTokenTransfer(address(_externalToken), _to, _value); return true; } /** * @dev external token transfer from a specific account * @param _externalToken the token contract * @param _from the account to spend token from * @param _to the destination address * @param _value the amount of tokens to transfer * @return bool which represents success */ function externalTokenTransferFrom( IERC20 _externalToken, address _from, address _to, uint256 _value ) public onlyOwner returns(bool) { address(_externalToken).safeTransferFrom(_from, _to, _value); emit ExternalTokenTransferFrom(address(_externalToken), _from, _to, _value); return true; } /** * @dev externalTokenApproval approve the spender address to spend a specified amount of tokens * on behalf of msg.sender. * @param _externalToken the address of the Token Contract * @param _spender address * @param _value the amount of ether (in Wei) which the approval is referring to. * @return bool which represents a success */ function externalTokenApproval(IERC20 _externalToken, address _spender, uint256 _value) public onlyOwner returns(bool) { address(_externalToken).safeApprove(_spender, _value); emit ExternalTokenApproval(address(_externalToken), _spender, _value); return true; } /** * @dev metaData emits an event with a string, should contain the hash of some meta data. * @param _metaData a string representing a hash of the meta data * @return bool which represents a success */ function metaData(string memory _metaData) public onlyOwner returns(bool) { emit MetaData(_metaData); return true; } } // File: contracts/universalSchemes/UniversalSchemeInterface.sol pragma solidity ^0.5.4; contract UniversalSchemeInterface { function getParametersFromController(Avatar _avatar) internal view returns(bytes32); } // File: contracts/globalConstraints/GlobalConstraintInterface.sol pragma solidity ^0.5.4; contract GlobalConstraintInterface { enum CallPhase { Pre, Post, PreAndPost } function pre( address _scheme, bytes32 _params, bytes32 _method ) public returns(bool); function post( address _scheme, bytes32 _params, bytes32 _method ) public returns(bool); /** * @dev when return if this globalConstraints is pre, post or both. * @return CallPhase enum indication Pre, Post or PreAndPost. */ function when() public returns(CallPhase); } // File: contracts/controller/ControllerInterface.sol pragma solidity ^0.5.4; /** * @title Controller contract * @dev A controller controls the organizations tokens ,reputation and avatar. * It is subject to a set of schemes and constraints that determine its behavior. * Each scheme has it own parameters and operation permissions. */ interface ControllerInterface { /** * @dev Mint `_amount` of reputation that are assigned to `_to` . * @param _amount amount of reputation to mint * @param _to beneficiary address * @return bool which represents a success */ function mintReputation(uint256 _amount, address _to, address _avatar) external returns(bool); /** * @dev Burns `_amount` of reputation from `_from` * @param _amount amount of reputation to burn * @param _from The address that will lose the reputation * @return bool which represents a success */ function burnReputation(uint256 _amount, address _from, address _avatar) external returns(bool); /** * @dev mint tokens . * @param _amount amount of token to mint * @param _beneficiary beneficiary address * @param _avatar address * @return bool which represents a success */ function mintTokens(uint256 _amount, address _beneficiary, address _avatar) external returns(bool); /** * @dev register or update a scheme * @param _scheme the address of the scheme * @param _paramsHash a hashed configuration of the usage of the scheme * @param _permissions the permissions the new scheme will have * @param _avatar address * @return bool which represents a success */ function registerScheme(address _scheme, bytes32 _paramsHash, bytes4 _permissions, address _avatar) external returns(bool); /** * @dev unregister a scheme * @param _avatar address * @param _scheme the address of the scheme * @return bool which represents a success */ function unregisterScheme(address _scheme, address _avatar) external returns(bool); /** * @dev unregister the caller's scheme * @param _avatar address * @return bool which represents a success */ function unregisterSelf(address _avatar) external returns(bool); /** * @dev add or update Global Constraint * @param _globalConstraint the address of the global constraint to be added. * @param _params the constraint parameters hash. * @param _avatar the avatar of the organization * @return bool which represents a success */ function addGlobalConstraint(address _globalConstraint, bytes32 _params, address _avatar) external returns(bool); /** * @dev remove Global Constraint * @param _globalConstraint the address of the global constraint to be remove. * @param _avatar the organization avatar. * @return bool which represents a success */ function removeGlobalConstraint (address _globalConstraint, address _avatar) external returns(bool); /** * @dev upgrade the Controller * The function will trigger an event 'UpgradeController'. * @param _newController the address of the new controller. * @param _avatar address * @return bool which represents a success */ function upgradeController(address _newController, Avatar _avatar) external returns(bool); /** * @dev perform a generic call to an arbitrary contract * @param _contract the contract's address to call * @param _data ABI-encoded contract call to call `_contract` address. * @param _avatar the controller's avatar address * @param _value value (ETH) to transfer with the transaction * @return bool -success * bytes - the return value of the called _contract's function. */ function genericCall(address _contract, bytes calldata _data, Avatar _avatar, uint256 _value) external returns(bool, bytes memory); /** * @dev send some ether * @param _amountInWei the amount of ether (in Wei) to send * @param _to address of the beneficiary * @param _avatar address * @return bool which represents a success */ function sendEther(uint256 _amountInWei, address payable _to, Avatar _avatar) external returns(bool); /** * @dev send some amount of arbitrary ERC20 Tokens * @param _externalToken the address of the Token Contract * @param _to address of the beneficiary * @param _value the amount of ether (in Wei) to send * @param _avatar address * @return bool which represents a success */ function externalTokenTransfer(IERC20 _externalToken, address _to, uint256 _value, Avatar _avatar) external returns(bool); /** * @dev transfer token "from" address "to" address * One must to approve the amount of tokens which can be spend from the * "from" account.This can be done using externalTokenApprove. * @param _externalToken the address of the Token Contract * @param _from address of the account to send from * @param _to address of the beneficiary * @param _value the amount of ether (in Wei) to send * @param _avatar address * @return bool which represents a success */ function externalTokenTransferFrom( IERC20 _externalToken, address _from, address _to, uint256 _value, Avatar _avatar) external returns(bool); /** * @dev externalTokenApproval approve the spender address to spend a specified amount of tokens * on behalf of msg.sender. * @param _externalToken the address of the Token Contract * @param _spender address * @param _value the amount of ether (in Wei) which the approval is referring to. * @return bool which represents a success */ function externalTokenApproval(IERC20 _externalToken, address _spender, uint256 _value, Avatar _avatar) external returns(bool); /** * @dev metaData emits an event with a string, should contain the hash of some meta data. * @param _metaData a string representing a hash of the meta data * @param _avatar Avatar * @return bool which represents a success */ function metaData(string calldata _metaData, Avatar _avatar) external returns(bool); /** * @dev getNativeReputation * @param _avatar the organization avatar. * @return organization native reputation */ function getNativeReputation(address _avatar) external view returns(address); function isSchemeRegistered( address _scheme, address _avatar) external view returns(bool); function getSchemeParameters(address _scheme, address _avatar) external view returns(bytes32); function getGlobalConstraintParameters(address _globalConstraint, address _avatar) external view returns(bytes32); function getSchemePermissions(address _scheme, address _avatar) external view returns(bytes4); /** * @dev globalConstraintsCount return the global constraint pre and post count * @return uint256 globalConstraintsPre count. * @return uint256 globalConstraintsPost count. */ function globalConstraintsCount(address _avatar) external view returns(uint, uint); function isGlobalConstraintRegistered(address _globalConstraint, address _avatar) external view returns(bool); } // File: contracts/universalSchemes/UniversalScheme.sol pragma solidity ^0.5.4; contract UniversalScheme is UniversalSchemeInterface { /** * @dev get the parameters for the current scheme from the controller */ function getParametersFromController(Avatar _avatar) internal view returns(bytes32) { require(ControllerInterface(_avatar.owner()).isSchemeRegistered(address(this), address(_avatar)), "scheme is not registered"); return ControllerInterface(_avatar.owner()).getSchemeParameters(address(this), address(_avatar)); } } // File: openzeppelin-solidity/contracts/cryptography/ECDSA.sol pragma solidity ^0.5.0; /** * @title Elliptic curve signature operations * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d * TODO Remove this library once solidity supports passing a signature to ecrecover. * See https://github.com/ethereum/solidity/issues/864 */ library ECDSA { /** * @dev Recover signer address from a message by using their signature * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. * @param signature bytes signature, the signature is generated using web3.eth.sign() */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { bytes32 r; bytes32 s; uint8 v; // Check the signature length if (signature.length != 65) { return (address(0)); } // Divide the signature in r, s and v variables // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } // Version of signature should be 27 or 28, but 0 and 1 are also possible versions if (v < 27) { v += 27; } // If the version is correct return the signer address if (v != 27 && v != 28) { return (address(0)); } else { return ecrecover(hash, v, r, s); } } /** * toEthSignedMessageHash * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:" * and hash the result */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } } // File: @daostack/infra/contracts/libs/RealMath.sol pragma solidity ^0.5.4; /** * RealMath: fixed-point math library, based on fractional and integer parts. * Using uint256 as real216x40, which isn't in Solidity yet. * Internally uses the wider uint256 for some math. * * Note that for addition, subtraction, and mod (%), you should just use the * built-in Solidity operators. Functions for these operations are not provided. * */ library RealMath { /** * How many total bits are there? */ uint256 constant private REAL_BITS = 256; /** * How many fractional bits are there? */ uint256 constant private REAL_FBITS = 40; /** * What's the first non-fractional bit */ uint256 constant private REAL_ONE = uint256(1) << REAL_FBITS; /** * Raise a real number to any positive integer power */ function pow(uint256 realBase, uint256 exponent) internal pure returns (uint256) { uint256 tempRealBase = realBase; uint256 tempExponent = exponent; // Start with the 0th power uint256 realResult = REAL_ONE; while (tempExponent != 0) { // While there are still bits set if ((tempExponent & 0x1) == 0x1) { // If the low bit is set, multiply in the (many-times-squared) base realResult = mul(realResult, tempRealBase); } // Shift off the low bit tempExponent = tempExponent >> 1; if (tempExponent != 0) { // Do the squaring tempRealBase = mul(tempRealBase, tempRealBase); } } // Return the final result. return realResult; } /** * Create a real from a rational fraction. */ function fraction(uint216 numerator, uint216 denominator) internal pure returns (uint256) { return div(uint256(numerator) * REAL_ONE, uint256(denominator) * REAL_ONE); } /** * Multiply one real by another. Truncates overflows. */ function mul(uint256 realA, uint256 realB) private pure returns (uint256) { // When multiplying fixed point in x.y and z.w formats we get (x+z).(y+w) format. // So we just have to clip off the extra REAL_FBITS fractional bits. uint256 res = realA * realB; require(res/realA == realB, "RealMath mul overflow"); return (res >> REAL_FBITS); } /** * Divide one real by another real. Truncates overflows. */ function div(uint256 realNumerator, uint256 realDenominator) private pure returns (uint256) { // We use the reverse of the multiplication trick: convert numerator from // x.y to (x+z).(y+w) fixed point, then divide by denom in z.w fixed point. return uint256((uint256(realNumerator) * REAL_ONE) / uint256(realDenominator)); } } // File: @daostack/infra/contracts/votingMachines/ProposalExecuteInterface.sol pragma solidity ^0.5.4; interface ProposalExecuteInterface { function executeProposal(bytes32 _proposalId, int _decision) external returns(bool); } // File: openzeppelin-solidity/contracts/math/Math.sol pragma solidity ^0.5.0; /** * @title Math * @dev Assorted math operations */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Calculates the average of two numbers. Since these are integers, * averages of an even and odd number cannot be represented, and will be * rounded down. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // File: @daostack/infra/contracts/votingMachines/GenesisProtocolLogic.sol pragma solidity ^0.5.4; /** * @title GenesisProtocol implementation -an organization's voting machine scheme. */ contract GenesisProtocolLogic is IntVoteInterface { using SafeMath for uint256; using Math for uint256; using RealMath for uint216; using RealMath for uint256; using Address for address; enum ProposalState { None, ExpiredInQueue, Executed, Queued, PreBoosted, Boosted, QuietEndingPeriod} enum ExecutionState { None, QueueBarCrossed, QueueTimeOut, PreBoostedBarCrossed, BoostedTimeOut, BoostedBarCrossed} //Organization's parameters struct Parameters { uint256 queuedVoteRequiredPercentage; // the absolute vote percentages bar. uint256 queuedVotePeriodLimit; //the time limit for a proposal to be in an absolute voting mode. uint256 boostedVotePeriodLimit; //the time limit for a proposal to be in boost mode. uint256 preBoostedVotePeriodLimit; //the time limit for a proposal //to be in an preparation state (stable) before boosted. uint256 thresholdConst; //constant for threshold calculation . //threshold =thresholdConst ** (numberOfBoostedProposals) uint256 limitExponentValue;// an upper limit for numberOfBoostedProposals //in the threshold calculation to prevent overflow uint256 quietEndingPeriod; //quite ending period uint256 proposingRepReward;//proposer reputation reward. uint256 votersReputationLossRatio;//Unsuccessful pre booster //voters lose votersReputationLossRatio% of their reputation. uint256 minimumDaoBounty; uint256 daoBountyConst;//The DAO downstake for each proposal is calculate according to the formula //(daoBountyConst * averageBoostDownstakes)/100 . uint256 activationTime;//the point in time after which proposals can be created. //if this address is set so only this address is allowed to vote of behalf of someone else. address voteOnBehalf; } struct Voter { uint256 vote; // YES(1) ,NO(2) uint256 reputation; // amount of voter's reputation bool preBoosted; } struct Staker { uint256 vote; // YES(1) ,NO(2) uint256 amount; // amount of staker's stake uint256 amount4Bounty;// amount of staker's stake used for bounty reward calculation. } struct Proposal { bytes32 organizationId; // the organization unique identifier the proposal is target to. address callbacks; // should fulfill voting callbacks interface. ProposalState state; uint256 winningVote; //the winning vote. address proposer; //the proposal boosted period limit . it is updated for the case of quiteWindow mode. uint256 currentBoostedVotePeriodLimit; bytes32 paramsHash; uint256 daoBountyRemain; //use for checking sum zero bounty claims.it is set at the proposing time. uint256 daoBounty; uint256 totalStakes;// Total number of tokens staked which can be redeemable by stakers. uint256 confidenceThreshold; uint256 secondsFromTimeOutTillExecuteBoosted; uint[3] times; //times[0] - submittedTime //times[1] - boostedPhaseTime //times[2] -preBoostedPhaseTime; bool daoRedeemItsWinnings; // vote reputation mapping(uint256 => uint256 ) votes; // vote reputation mapping(uint256 => uint256 ) preBoostedVotes; // address voter mapping(address => Voter ) voters; // vote stakes mapping(uint256 => uint256 ) stakes; // address staker mapping(address => Staker ) stakers; } event Stake(bytes32 indexed _proposalId, address indexed _organization, address indexed _staker, uint256 _vote, uint256 _amount ); event Redeem(bytes32 indexed _proposalId, address indexed _organization, address indexed _beneficiary, uint256 _amount ); event RedeemDaoBounty(bytes32 indexed _proposalId, address indexed _organization, address indexed _beneficiary, uint256 _amount ); event RedeemReputation(bytes32 indexed _proposalId, address indexed _organization, address indexed _beneficiary, uint256 _amount ); event StateChange(bytes32 indexed _proposalId, ProposalState _proposalState); event GPExecuteProposal(bytes32 indexed _proposalId, ExecutionState _executionState); event ExpirationCallBounty(bytes32 indexed _proposalId, address indexed _beneficiary, uint256 _amount); event ConfidenceLevelChange(bytes32 indexed _proposalId, uint256 _confidenceThreshold); mapping(bytes32=>Parameters) public parameters; // A mapping from hashes to parameters mapping(bytes32=>Proposal) public proposals; // Mapping from the ID of the proposal to the proposal itself. mapping(bytes32=>uint) public orgBoostedProposalsCnt; //organizationId => organization mapping(bytes32 => address ) public organizations; //organizationId => averageBoostDownstakes mapping(bytes32 => uint256 ) public averagesDownstakesOfBoosted; uint256 constant public NUM_OF_CHOICES = 2; uint256 constant public NO = 2; uint256 constant public YES = 1; uint256 public proposalsCnt; // Total number of proposals IERC20 public stakingToken; address constant private GEN_TOKEN_ADDRESS = 0x543Ff227F64Aa17eA132Bf9886cAb5DB55DCAddf; uint256 constant private MAX_BOOSTED_PROPOSALS = 4096; /** * @dev Constructor */ constructor(IERC20 _stakingToken) public { //The GEN token (staking token) address is hard coded in the contract by GEN_TOKEN_ADDRESS . //This will work for a network which already hosted the GEN token on this address (e.g mainnet). //If such contract address does not exist in the network (e.g ganache) //the contract will use the _stakingToken param as the //staking token address. if (address(GEN_TOKEN_ADDRESS).isContract()) { stakingToken = IERC20(GEN_TOKEN_ADDRESS); } else { stakingToken = _stakingToken; } } /** * @dev Check that the proposal is votable * a proposal is votable if it is in one of the following states: * PreBoosted,Boosted,QuietEndingPeriod or Queued */ modifier votable(bytes32 _proposalId) { require(_isVotable(_proposalId)); _; } /** * @dev register a new proposal with the given parameters. Every proposal has a unique ID which is being * generated by calculating keccak256 of a incremented counter. * @param _paramsHash parameters hash * @param _proposer address * @param _organization address */ function propose(uint256, bytes32 _paramsHash, address _proposer, address _organization) external returns(bytes32) { // solhint-disable-next-line not-rely-on-time require(now > parameters[_paramsHash].activationTime, "not active yet"); //Check parameters existence. require(parameters[_paramsHash].queuedVoteRequiredPercentage >= 50); // Generate a unique ID: bytes32 proposalId = keccak256(abi.encodePacked(this, proposalsCnt)); proposalsCnt = proposalsCnt.add(1); // Open proposal: Proposal memory proposal; proposal.callbacks = msg.sender; proposal.organizationId = keccak256(abi.encodePacked(msg.sender, _organization)); proposal.state = ProposalState.Queued; // solhint-disable-next-line not-rely-on-time proposal.times[0] = now;//submitted time proposal.currentBoostedVotePeriodLimit = parameters[_paramsHash].boostedVotePeriodLimit; proposal.proposer = _proposer; proposal.winningVote = NO; proposal.paramsHash = _paramsHash; if (organizations[proposal.organizationId] == address(0)) { if (_organization == address(0)) { organizations[proposal.organizationId] = msg.sender; } else { organizations[proposal.organizationId] = _organization; } } //calc dao bounty uint256 daoBounty = parameters[_paramsHash].daoBountyConst.mul(averagesDownstakesOfBoosted[proposal.organizationId]).div(100); proposal.daoBountyRemain = daoBounty.max(parameters[_paramsHash].minimumDaoBounty); proposals[proposalId] = proposal; proposals[proposalId].stakes[NO] = proposal.daoBountyRemain;//dao downstake on the proposal emit NewProposal(proposalId, organizations[proposal.organizationId], NUM_OF_CHOICES, _proposer, _paramsHash); return proposalId; } /** * @dev executeBoosted try to execute a boosted or QuietEndingPeriod proposal if it is expired * it rewards the msg.sender with P % of the proposal's upstakes upon a successful call to this function. * P = t/150, where t is the number of seconds passed since the the proposal's timeout. * P is capped by 10%. * @param _proposalId the id of the proposal * @return uint256 expirationCallBounty the bounty amount for the expiration call */ function executeBoosted(bytes32 _proposalId) external returns(uint256 expirationCallBounty) { Proposal storage proposal = proposals[_proposalId]; require(proposal.state == ProposalState.Boosted || proposal.state == ProposalState.QuietEndingPeriod, "proposal state in not Boosted nor QuietEndingPeriod"); require(_execute(_proposalId), "proposal need to expire"); proposal.secondsFromTimeOutTillExecuteBoosted = // solhint-disable-next-line not-rely-on-time now.sub(proposal.currentBoostedVotePeriodLimit.add(proposal.times[1])); expirationCallBounty = calcExecuteCallBounty(_proposalId); proposal.totalStakes = proposal.totalStakes.sub(expirationCallBounty); require(stakingToken.transfer(msg.sender, expirationCallBounty), "transfer to msg.sender failed"); emit ExpirationCallBounty(_proposalId, msg.sender, expirationCallBounty); } /** * @dev hash the parameters, save them if necessary, and return the hash value * @param _params a parameters array * _params[0] - _queuedVoteRequiredPercentage, * _params[1] - _queuedVotePeriodLimit, //the time limit for a proposal to be in an absolute voting mode. * _params[2] - _boostedVotePeriodLimit, //the time limit for a proposal to be in an relative voting mode. * _params[3] - _preBoostedVotePeriodLimit, //the time limit for a proposal to be in an preparation * state (stable) before boosted. * _params[4] -_thresholdConst * _params[5] -_quietEndingPeriod * _params[6] -_proposingRepReward * _params[7] -_votersReputationLossRatio * _params[8] -_minimumDaoBounty * _params[9] -_daoBountyConst * _params[10] -_activationTime * @param _voteOnBehalf - authorized to vote on behalf of others. */ function setParameters( uint[11] calldata _params, //use array here due to stack too deep issue. address _voteOnBehalf ) external returns(bytes32) { require(_params[0] <= 100 && _params[0] >= 50, "50 <= queuedVoteRequiredPercentage <= 100"); require(_params[4] <= 16000 && _params[4] > 1000, "1000 < thresholdConst <= 16000"); require(_params[7] <= 100, "votersReputationLossRatio <= 100"); require(_params[2] >= _params[5], "boostedVotePeriodLimit >= quietEndingPeriod"); require(_params[8] > 0, "minimumDaoBounty should be > 0"); require(_params[9] > 0, "daoBountyConst should be > 0"); bytes32 paramsHash = getParametersHash(_params, _voteOnBehalf); //set a limit for power for a given alpha to prevent overflow uint256 limitExponent = 172;//for alpha less or equal 2 uint256 j = 2; for (uint256 i = 2000; i < 16000; i = i*2) { if ((_params[4] > i) && (_params[4] <= i*2)) { limitExponent = limitExponent/j; break; } j++; } parameters[paramsHash] = Parameters({ queuedVoteRequiredPercentage: _params[0], queuedVotePeriodLimit: _params[1], boostedVotePeriodLimit: _params[2], preBoostedVotePeriodLimit: _params[3], thresholdConst:uint216(_params[4]).fraction(uint216(1000)), limitExponentValue:limitExponent, quietEndingPeriod: _params[5], proposingRepReward: _params[6], votersReputationLossRatio:_params[7], minimumDaoBounty:_params[8], daoBountyConst:_params[9], activationTime:_params[10], voteOnBehalf:_voteOnBehalf }); return paramsHash; } /** * @dev redeem a reward for a successful stake, vote or proposing. * The function use a beneficiary address as a parameter (and not msg.sender) to enable * users to redeem on behalf of someone else. * @param _proposalId the ID of the proposal * @param _beneficiary - the beneficiary address * @return rewards - * [0] stakerTokenReward * [1] voterReputationReward * [2] proposerReputationReward */ // solhint-disable-next-line function-max-lines,code-complexity function redeem(bytes32 _proposalId, address _beneficiary) public returns (uint[3] memory rewards) { Proposal storage proposal = proposals[_proposalId]; require((proposal.state == ProposalState.Executed)||(proposal.state == ProposalState.ExpiredInQueue), "Proposal should be Executed or ExpiredInQueue"); Parameters memory params = parameters[proposal.paramsHash]; //as staker Staker storage staker = proposal.stakers[_beneficiary]; uint256 totalWinningStakes = proposal.stakes[proposal.winningVote]; uint256 totalStakesLeftAfterCallBounty = proposal.stakes[NO].add(proposal.stakes[YES]).sub(calcExecuteCallBounty(_proposalId)); if (staker.amount > 0) { if (proposal.state == ProposalState.ExpiredInQueue) { //Stakes of a proposal that expires in Queue are sent back to stakers rewards[0] = staker.amount; } else if (staker.vote == proposal.winningVote) { if (staker.vote == YES) { if (proposal.daoBounty < totalStakesLeftAfterCallBounty) { uint256 _totalStakes = totalStakesLeftAfterCallBounty.sub(proposal.daoBounty); rewards[0] = (staker.amount.mul(_totalStakes))/totalWinningStakes; } } else { rewards[0] = (staker.amount.mul(totalStakesLeftAfterCallBounty))/totalWinningStakes; } } staker.amount = 0; } //dao redeem its winnings if (proposal.daoRedeemItsWinnings == false && _beneficiary == organizations[proposal.organizationId] && proposal.state != ProposalState.ExpiredInQueue && proposal.winningVote == NO) { rewards[0] = rewards[0] .add((proposal.daoBounty.mul(totalStakesLeftAfterCallBounty))/totalWinningStakes) .sub(proposal.daoBounty); proposal.daoRedeemItsWinnings = true; } //as voter Voter storage voter = proposal.voters[_beneficiary]; if ((voter.reputation != 0) && (voter.preBoosted)) { if (proposal.state == ProposalState.ExpiredInQueue) { //give back reputation for the voter rewards[1] = ((voter.reputation.mul(params.votersReputationLossRatio))/100); } else if (proposal.winningVote == voter.vote) { uint256 lostReputation; if (proposal.winningVote == YES) { lostReputation = proposal.preBoostedVotes[NO]; } else { lostReputation = proposal.preBoostedVotes[YES]; } lostReputation = (lostReputation.mul(params.votersReputationLossRatio))/100; rewards[1] = ((voter.reputation.mul(params.votersReputationLossRatio))/100) .add((voter.reputation.mul(lostReputation))/proposal.preBoostedVotes[proposal.winningVote]); } voter.reputation = 0; } //as proposer if ((proposal.proposer == _beneficiary)&&(proposal.winningVote == YES)&&(proposal.proposer != address(0))) { rewards[2] = params.proposingRepReward; proposal.proposer = address(0); } if (rewards[0] != 0) { proposal.totalStakes = proposal.totalStakes.sub(rewards[0]); require(stakingToken.transfer(_beneficiary, rewards[0]), "transfer to beneficiary failed"); emit Redeem(_proposalId, organizations[proposal.organizationId], _beneficiary, rewards[0]); } if (rewards[1].add(rewards[2]) != 0) { VotingMachineCallbacksInterface(proposal.callbacks) .mintReputation(rewards[1].add(rewards[2]), _beneficiary, _proposalId); emit RedeemReputation( _proposalId, organizations[proposal.organizationId], _beneficiary, rewards[1].add(rewards[2]) ); } } /** * @dev redeemDaoBounty a reward for a successful stake. * The function use a beneficiary address as a parameter (and not msg.sender) to enable * users to redeem on behalf of someone else. * @param _proposalId the ID of the proposal * @param _beneficiary - the beneficiary address * @return redeemedAmount - redeem token amount * @return potentialAmount - potential redeem token amount(if there is enough tokens bounty at the organization ) */ function redeemDaoBounty(bytes32 _proposalId, address _beneficiary) public returns(uint256 redeemedAmount, uint256 potentialAmount) { Proposal storage proposal = proposals[_proposalId]; require(proposal.state == ProposalState.Executed); uint256 totalWinningStakes = proposal.stakes[proposal.winningVote]; Staker storage staker = proposal.stakers[_beneficiary]; if ( (staker.amount4Bounty > 0)&& (staker.vote == proposal.winningVote)&& (proposal.winningVote == YES)&& (totalWinningStakes != 0)) { //as staker potentialAmount = (staker.amount4Bounty * proposal.daoBounty)/totalWinningStakes; } if ((potentialAmount != 0)&& (VotingMachineCallbacksInterface(proposal.callbacks) .balanceOfStakingToken(stakingToken, _proposalId) >= potentialAmount)) { staker.amount4Bounty = 0; proposal.daoBountyRemain = proposal.daoBountyRemain.sub(potentialAmount); require( VotingMachineCallbacksInterface(proposal.callbacks) .stakingTokenTransfer(stakingToken, _beneficiary, potentialAmount, _proposalId)); redeemedAmount = potentialAmount; emit RedeemDaoBounty(_proposalId, organizations[proposal.organizationId], _beneficiary, redeemedAmount); } } /** * @dev calcExecuteCallBounty calculate the execute boosted call bounty * @param _proposalId the ID of the proposal * @return uint256 executeCallBounty */ function calcExecuteCallBounty(bytes32 _proposalId) public view returns(uint256) { uint maxRewardSeconds = 1500; uint rewardSeconds = uint256(maxRewardSeconds).min(proposals[_proposalId].secondsFromTimeOutTillExecuteBoosted); return rewardSeconds.mul(proposals[_proposalId].stakes[YES]).div(maxRewardSeconds*10); } /** * @dev shouldBoost check if a proposal should be shifted to boosted phase. * @param _proposalId the ID of the proposal * @return bool true or false. */ function shouldBoost(bytes32 _proposalId) public view returns(bool) { Proposal memory proposal = proposals[_proposalId]; return (_score(_proposalId) > threshold(proposal.paramsHash, proposal.organizationId)); } /** * @dev threshold return the organization's score threshold which required by * a proposal to shift to boosted state. * This threshold is dynamically set and it depend on the number of boosted proposal. * @param _organizationId the organization identifier * @param _paramsHash the organization parameters hash * @return uint256 organization's score threshold as real number. */ function threshold(bytes32 _paramsHash, bytes32 _organizationId) public view returns(uint256) { uint256 power = orgBoostedProposalsCnt[_organizationId]; Parameters storage params = parameters[_paramsHash]; if (power > params.limitExponentValue) { power = params.limitExponentValue; } return params.thresholdConst.pow(power); } /** * @dev hashParameters returns a hash of the given parameters */ function getParametersHash( uint[11] memory _params,//use array here due to stack too deep issue. address _voteOnBehalf ) public pure returns(bytes32) { //double call to keccak256 to avoid deep stack issue when call with too many params. return keccak256( abi.encodePacked( keccak256( abi.encodePacked( _params[0], _params[1], _params[2], _params[3], _params[4], _params[5], _params[6], _params[7], _params[8], _params[9], _params[10]) ), _voteOnBehalf )); } /** * @dev execute check if the proposal has been decided, and if so, execute the proposal * @param _proposalId the id of the proposal * @return bool true - the proposal has been executed * false - otherwise. */ // solhint-disable-next-line function-max-lines,code-complexity function _execute(bytes32 _proposalId) internal votable(_proposalId) returns(bool) { Proposal storage proposal = proposals[_proposalId]; Parameters memory params = parameters[proposal.paramsHash]; Proposal memory tmpProposal = proposal; uint256 totalReputation = VotingMachineCallbacksInterface(proposal.callbacks).getTotalReputationSupply(_proposalId); //first divide by 100 to prevent overflow uint256 executionBar = (totalReputation/100) * params.queuedVoteRequiredPercentage; ExecutionState executionState = ExecutionState.None; uint256 averageDownstakesOfBoosted; uint256 confidenceThreshold; if (proposal.votes[proposal.winningVote] > executionBar) { // someone crossed the absolute vote execution bar. if (proposal.state == ProposalState.Queued) { executionState = ExecutionState.QueueBarCrossed; } else if (proposal.state == ProposalState.PreBoosted) { executionState = ExecutionState.PreBoostedBarCrossed; } else { executionState = ExecutionState.BoostedBarCrossed; } proposal.state = ProposalState.Executed; } else { if (proposal.state == ProposalState.Queued) { // solhint-disable-next-line not-rely-on-time if ((now - proposal.times[0]) >= params.queuedVotePeriodLimit) { proposal.state = ProposalState.ExpiredInQueue; proposal.winningVote = NO; executionState = ExecutionState.QueueTimeOut; } else { confidenceThreshold = threshold(proposal.paramsHash, proposal.organizationId); if (_score(_proposalId) > confidenceThreshold) { //change proposal mode to PreBoosted mode. proposal.state = ProposalState.PreBoosted; // solhint-disable-next-line not-rely-on-time proposal.times[2] = now; proposal.confidenceThreshold = confidenceThreshold; } } } if (proposal.state == ProposalState.PreBoosted) { confidenceThreshold = threshold(proposal.paramsHash, proposal.organizationId); // solhint-disable-next-line not-rely-on-time if ((now - proposal.times[2]) >= params.preBoostedVotePeriodLimit) { if (_score(_proposalId) > confidenceThreshold) { if (orgBoostedProposalsCnt[proposal.organizationId] < MAX_BOOSTED_PROPOSALS) { //change proposal mode to Boosted mode. proposal.state = ProposalState.Boosted; // solhint-disable-next-line not-rely-on-time proposal.times[1] = now; orgBoostedProposalsCnt[proposal.organizationId]++; //add a value to average -> average = average + ((value - average) / nbValues) averageDownstakesOfBoosted = averagesDownstakesOfBoosted[proposal.organizationId]; // solium-disable-next-line indentation averagesDownstakesOfBoosted[proposal.organizationId] = uint256(int256(averageDownstakesOfBoosted) + ((int256(proposal.stakes[NO])-int256(averageDownstakesOfBoosted))/ int256(orgBoostedProposalsCnt[proposal.organizationId]))); } } else { proposal.state = ProposalState.Queued; } } else { //check the Confidence level is stable uint256 proposalScore = _score(_proposalId); if (proposalScore <= proposal.confidenceThreshold.min(confidenceThreshold)) { proposal.state = ProposalState.Queued; } else if (proposal.confidenceThreshold > proposalScore) { proposal.confidenceThreshold = confidenceThreshold; emit ConfidenceLevelChange(_proposalId, confidenceThreshold); } } } } if ((proposal.state == ProposalState.Boosted) || (proposal.state == ProposalState.QuietEndingPeriod)) { // solhint-disable-next-line not-rely-on-time if ((now - proposal.times[1]) >= proposal.currentBoostedVotePeriodLimit) { proposal.state = ProposalState.Executed; executionState = ExecutionState.BoostedTimeOut; } } if (executionState != ExecutionState.None) { if ((executionState == ExecutionState.BoostedTimeOut) || (executionState == ExecutionState.BoostedBarCrossed)) { orgBoostedProposalsCnt[tmpProposal.organizationId] = orgBoostedProposalsCnt[tmpProposal.organizationId].sub(1); //remove a value from average = ((average * nbValues) - value) / (nbValues - 1); uint256 boostedProposals = orgBoostedProposalsCnt[tmpProposal.organizationId]; if (boostedProposals == 0) { averagesDownstakesOfBoosted[proposal.organizationId] = 0; } else { averageDownstakesOfBoosted = averagesDownstakesOfBoosted[proposal.organizationId]; averagesDownstakesOfBoosted[proposal.organizationId] = (averageDownstakesOfBoosted.mul(boostedProposals+1).sub(proposal.stakes[NO]))/boostedProposals; } } emit ExecuteProposal( _proposalId, organizations[proposal.organizationId], proposal.winningVote, totalReputation ); emit GPExecuteProposal(_proposalId, executionState); ProposalExecuteInterface(proposal.callbacks).executeProposal(_proposalId, int(proposal.winningVote)); proposal.daoBounty = proposal.daoBountyRemain; } if (tmpProposal.state != proposal.state) { emit StateChange(_proposalId, proposal.state); } return (executionState != ExecutionState.None); } /** * @dev staking function * @param _proposalId id of the proposal * @param _vote NO(2) or YES(1). * @param _amount the betting amount * @return bool true - the proposal has been executed * false - otherwise. */ function _stake(bytes32 _proposalId, uint256 _vote, uint256 _amount, address _staker) internal returns(bool) { // 0 is not a valid vote. require(_vote <= NUM_OF_CHOICES && _vote > 0, "wrong vote value"); require(_amount > 0, "staking amount should be >0"); if (_execute(_proposalId)) { return true; } Proposal storage proposal = proposals[_proposalId]; if ((proposal.state != ProposalState.PreBoosted) && (proposal.state != ProposalState.Queued)) { return false; } // enable to increase stake only on the previous stake vote Staker storage staker = proposal.stakers[_staker]; if ((staker.amount > 0) && (staker.vote != _vote)) { return false; } uint256 amount = _amount; require(stakingToken.transferFrom(_staker, address(this), amount), "fail transfer from staker"); proposal.totalStakes = proposal.totalStakes.add(amount); //update totalRedeemableStakes staker.amount = staker.amount.add(amount); //This is to prevent average downstakes calculation overflow //Note that any how GEN cap is 100000000 ether. require(staker.amount <= 0x100000000000000000000000000000000, "staking amount is too high"); require(proposal.totalStakes <= uint256(0x100000000000000000000000000000000).sub(proposal.daoBountyRemain), "total stakes is too high"); if (_vote == YES) { staker.amount4Bounty = staker.amount4Bounty.add(amount); } staker.vote = _vote; proposal.stakes[_vote] = amount.add(proposal.stakes[_vote]); emit Stake(_proposalId, organizations[proposal.organizationId], _staker, _vote, _amount); return _execute(_proposalId); } /** * @dev Vote for a proposal, if the voter already voted, cancel the last vote and set a new one instead * @param _proposalId id of the proposal * @param _voter used in case the vote is cast for someone else * @param _vote a value between 0 to and the proposal's number of choices. * @param _rep how many reputation the voter would like to stake for this vote. * if _rep==0 so the voter full reputation will be use. * @return true in case of proposal execution otherwise false * throws if proposal is not open or if it has been executed * NB: executes the proposal if a decision has been reached */ // solhint-disable-next-line function-max-lines,code-complexity function internalVote(bytes32 _proposalId, address _voter, uint256 _vote, uint256 _rep) internal returns(bool) { require(_vote <= NUM_OF_CHOICES && _vote > 0, "0 < _vote <= 2"); if (_execute(_proposalId)) { return true; } Parameters memory params = parameters[proposals[_proposalId].paramsHash]; Proposal storage proposal = proposals[_proposalId]; // Check voter has enough reputation: uint256 reputation = VotingMachineCallbacksInterface(proposal.callbacks).reputationOf(_voter, _proposalId); require(reputation > 0, "_voter must have reputation"); require(reputation >= _rep, "reputation >= _rep"); uint256 rep = _rep; if (rep == 0) { rep = reputation; } // If this voter has already voted, return false. if (proposal.voters[_voter].reputation != 0) { return false; } // The voting itself: proposal.votes[_vote] = rep.add(proposal.votes[_vote]); //check if the current winningVote changed or there is a tie. //for the case there is a tie the current winningVote set to NO. if ((proposal.votes[_vote] > proposal.votes[proposal.winningVote]) || ((proposal.votes[NO] == proposal.votes[proposal.winningVote]) && proposal.winningVote == YES)) { if (proposal.state == ProposalState.Boosted && // solhint-disable-next-line not-rely-on-time ((now - proposal.times[1]) >= (params.boostedVotePeriodLimit - params.quietEndingPeriod))|| proposal.state == ProposalState.QuietEndingPeriod) { //quietEndingPeriod if (proposal.state != ProposalState.QuietEndingPeriod) { proposal.currentBoostedVotePeriodLimit = params.quietEndingPeriod; proposal.state = ProposalState.QuietEndingPeriod; emit StateChange(_proposalId, proposal.state); } // solhint-disable-next-line not-rely-on-time proposal.times[1] = now; } proposal.winningVote = _vote; } proposal.voters[_voter] = Voter({ reputation: rep, vote: _vote, preBoosted:((proposal.state == ProposalState.PreBoosted) || (proposal.state == ProposalState.Queued)) }); if ((proposal.state == ProposalState.PreBoosted) || (proposal.state == ProposalState.Queued)) { proposal.preBoostedVotes[_vote] = rep.add(proposal.preBoostedVotes[_vote]); uint256 reputationDeposit = (params.votersReputationLossRatio.mul(rep))/100; VotingMachineCallbacksInterface(proposal.callbacks).burnReputation(reputationDeposit, _voter, _proposalId); } emit VoteProposal(_proposalId, organizations[proposal.organizationId], _voter, _vote, rep); return _execute(_proposalId); } /** * @dev _score return the proposal score (Confidence level) * For dual choice proposal S = (S+)/(S-) * @param _proposalId the ID of the proposal * @return uint256 proposal score as real number. */ function _score(bytes32 _proposalId) internal view returns(uint256) { Proposal storage proposal = proposals[_proposalId]; //proposal.stakes[NO] cannot be zero as the dao downstake > 0 for each proposal. return uint216(proposal.stakes[YES]).fraction(uint216(proposal.stakes[NO])); } /** * @dev _isVotable check if the proposal is votable * @param _proposalId the ID of the proposal * @return bool true or false */ function _isVotable(bytes32 _proposalId) internal view returns(bool) { ProposalState pState = proposals[_proposalId].state; return ((pState == ProposalState.PreBoosted)|| (pState == ProposalState.Boosted)|| (pState == ProposalState.QuietEndingPeriod)|| (pState == ProposalState.Queued) ); } } // File: @daostack/infra/contracts/votingMachines/GenesisProtocol.sol pragma solidity ^0.5.4; /** * @title GenesisProtocol implementation -an organization's voting machine scheme. */ contract GenesisProtocol is IntVoteInterface, GenesisProtocolLogic { using ECDSA for bytes32; // Digest describing the data the user signs according EIP 712. // Needs to match what is passed to Metamask. bytes32 public constant DELEGATION_HASH_EIP712 = keccak256(abi.encodePacked( "address GenesisProtocolAddress", "bytes32 ProposalId", "uint256 Vote", "uint256 AmountToStake", "uint256 Nonce" )); mapping(address=>uint256) public stakesNonce; //stakes Nonce /** * @dev Constructor */ constructor(IERC20 _stakingToken) public // solhint-disable-next-line no-empty-blocks GenesisProtocolLogic(_stakingToken) { } /** * @dev staking function * @param _proposalId id of the proposal * @param _vote NO(2) or YES(1). * @param _amount the betting amount * @return bool true - the proposal has been executed * false - otherwise. */ function stake(bytes32 _proposalId, uint256 _vote, uint256 _amount) external returns(bool) { return _stake(_proposalId, _vote, _amount, msg.sender); } /** * @dev stakeWithSignature function * @param _proposalId id of the proposal * @param _vote NO(2) or YES(1). * @param _amount the betting amount * @param _nonce nonce value ,it is part of the signature to ensure that a signature can be received only once. * @param _signatureType signature type 1 - for web3.eth.sign 2 - for eth_signTypedData according to EIP #712. * @param _signature - signed data by the staker * @return bool true - the proposal has been executed * false - otherwise. */ function stakeWithSignature( bytes32 _proposalId, uint256 _vote, uint256 _amount, uint256 _nonce, uint256 _signatureType, bytes calldata _signature ) external returns(bool) { // Recreate the digest the user signed bytes32 delegationDigest; if (_signatureType == 2) { delegationDigest = keccak256( abi.encodePacked( DELEGATION_HASH_EIP712, keccak256( abi.encodePacked( address(this), _proposalId, _vote, _amount, _nonce) ) ) ); } else { delegationDigest = keccak256( abi.encodePacked( address(this), _proposalId, _vote, _amount, _nonce) ).toEthSignedMessageHash(); } address staker = delegationDigest.recover(_signature); //a garbage staker address due to wrong signature will revert due to lack of approval and funds. require(staker != address(0), "staker address cannot be 0"); require(stakesNonce[staker] == _nonce); stakesNonce[staker] = stakesNonce[staker].add(1); return _stake(_proposalId, _vote, _amount, staker); } /** * @dev voting function * @param _proposalId id of the proposal * @param _vote NO(2) or YES(1). * @param _amount the reputation amount to vote with . if _amount == 0 it will use all voter reputation. * @param _voter voter address * @return bool true - the proposal has been executed * false - otherwise. */ function vote(bytes32 _proposalId, uint256 _vote, uint256 _amount, address _voter) external votable(_proposalId) returns(bool) { Proposal storage proposal = proposals[_proposalId]; Parameters memory params = parameters[proposal.paramsHash]; address voter; if (params.voteOnBehalf != address(0)) { require(msg.sender == params.voteOnBehalf); voter = _voter; } else { voter = msg.sender; } return internalVote(_proposalId, voter, _vote, _amount); } /** * @dev Cancel the vote of the msg.sender. * cancel vote is not allow in genesisProtocol so this function doing nothing. * This function is here in order to comply to the IntVoteInterface . */ function cancelVote(bytes32 _proposalId) external votable(_proposalId) { //this is not allowed return; } /** * @dev execute check if the proposal has been decided, and if so, execute the proposal * @param _proposalId the id of the proposal * @return bool true - the proposal has been executed * false - otherwise. */ function execute(bytes32 _proposalId) external votable(_proposalId) returns(bool) { return _execute(_proposalId); } /** * @dev getNumberOfChoices returns the number of choices possible in this proposal * @return uint256 that contains number of choices */ function getNumberOfChoices(bytes32) external view returns(uint256) { return NUM_OF_CHOICES; } /** * @dev getProposalTimes returns proposals times variables. * @param _proposalId id of the proposal * @return proposals times array */ function getProposalTimes(bytes32 _proposalId) external view returns(uint[3] memory times) { return proposals[_proposalId].times; } /** * @dev voteInfo returns the vote and the amount of reputation of the user committed to this proposal * @param _proposalId the ID of the proposal * @param _voter the address of the voter * @return uint256 vote - the voters vote * uint256 reputation - amount of reputation committed by _voter to _proposalId */ function voteInfo(bytes32 _proposalId, address _voter) external view returns(uint, uint) { Voter memory voter = proposals[_proposalId].voters[_voter]; return (voter.vote, voter.reputation); } /** * @dev voteStatus returns the reputation voted for a proposal for a specific voting choice. * @param _proposalId the ID of the proposal * @param _choice the index in the * @return voted reputation for the given choice */ function voteStatus(bytes32 _proposalId, uint256 _choice) external view returns(uint256) { return proposals[_proposalId].votes[_choice]; } /** * @dev isVotable check if the proposal is votable * @param _proposalId the ID of the proposal * @return bool true or false */ function isVotable(bytes32 _proposalId) external view returns(bool) { return _isVotable(_proposalId); } /** * @dev proposalStatus return the total votes and stakes for a given proposal * @param _proposalId the ID of the proposal * @return uint256 preBoostedVotes YES * @return uint256 preBoostedVotes NO * @return uint256 total stakes YES * @return uint256 total stakes NO */ function proposalStatus(bytes32 _proposalId) external view returns(uint256, uint256, uint256, uint256) { return ( proposals[_proposalId].preBoostedVotes[YES], proposals[_proposalId].preBoostedVotes[NO], proposals[_proposalId].stakes[YES], proposals[_proposalId].stakes[NO] ); } /** * @dev getProposalOrganization return the organizationId for a given proposal * @param _proposalId the ID of the proposal * @return bytes32 organization identifier */ function getProposalOrganization(bytes32 _proposalId) external view returns(bytes32) { return (proposals[_proposalId].organizationId); } /** * @dev getStaker return the vote and stake amount for a given proposal and staker * @param _proposalId the ID of the proposal * @param _staker staker address * @return uint256 vote * @return uint256 amount */ function getStaker(bytes32 _proposalId, address _staker) external view returns(uint256, uint256) { return (proposals[_proposalId].stakers[_staker].vote, proposals[_proposalId].stakers[_staker].amount); } /** * @dev voteStake return the amount stakes for a given proposal and vote * @param _proposalId the ID of the proposal * @param _vote vote number * @return uint256 stake amount */ function voteStake(bytes32 _proposalId, uint256 _vote) external view returns(uint256) { return proposals[_proposalId].stakes[_vote]; } /** * @dev voteStake return the winningVote for a given proposal * @param _proposalId the ID of the proposal * @return uint256 winningVote */ function winningVote(bytes32 _proposalId) external view returns(uint256) { return proposals[_proposalId].winningVote; } /** * @dev voteStake return the state for a given proposal * @param _proposalId the ID of the proposal * @return ProposalState proposal state */ function state(bytes32 _proposalId) external view returns(ProposalState) { return proposals[_proposalId].state; } /** * @dev isAbstainAllow returns if the voting machine allow abstain (0) * @return bool true or false */ function isAbstainAllow() external pure returns(bool) { return false; } /** * @dev getAllowedRangeOfChoices returns the allowed range of choices for a voting machine. * @return min - minimum number of choices max - maximum number of choices */ function getAllowedRangeOfChoices() external pure returns(uint256 min, uint256 max) { return (YES, NO); } /** * @dev score return the proposal score * @param _proposalId the ID of the proposal * @return uint256 proposal score. */ function score(bytes32 _proposalId) public view returns(uint256) { return _score(_proposalId); } } // File: contracts/votingMachines/VotingMachineCallbacks.sol pragma solidity ^0.5.4; contract VotingMachineCallbacks is VotingMachineCallbacksInterface { struct ProposalInfo { uint256 blockNumber; // the proposal's block number Avatar avatar; // the proposal's avatar } modifier onlyVotingMachine(bytes32 _proposalId) { require(proposalsInfo[msg.sender][_proposalId].avatar != Avatar(address(0)), "only VotingMachine"); _; } // VotingMaching -> proposalId -> ProposalInfo mapping(address => mapping(bytes32 => ProposalInfo)) public proposalsInfo; function mintReputation(uint256 _amount, address _beneficiary, bytes32 _proposalId) external onlyVotingMachine(_proposalId) returns(bool) { Avatar avatar = proposalsInfo[msg.sender][_proposalId].avatar; if (avatar == Avatar(0)) { return false; } return ControllerInterface(avatar.owner()).mintReputation(_amount, _beneficiary, address(avatar)); } function burnReputation(uint256 _amount, address _beneficiary, bytes32 _proposalId) external onlyVotingMachine(_proposalId) returns(bool) { Avatar avatar = proposalsInfo[msg.sender][_proposalId].avatar; if (avatar == Avatar(0)) { return false; } return ControllerInterface(avatar.owner()).burnReputation(_amount, _beneficiary, address(avatar)); } function stakingTokenTransfer( IERC20 _stakingToken, address _beneficiary, uint256 _amount, bytes32 _proposalId) external onlyVotingMachine(_proposalId) returns(bool) { Avatar avatar = proposalsInfo[msg.sender][_proposalId].avatar; if (avatar == Avatar(0)) { return false; } return ControllerInterface(avatar.owner()).externalTokenTransfer(_stakingToken, _beneficiary, _amount, avatar); } function balanceOfStakingToken(IERC20 _stakingToken, bytes32 _proposalId) external view returns(uint256) { Avatar avatar = proposalsInfo[msg.sender][_proposalId].avatar; if (proposalsInfo[msg.sender][_proposalId].avatar == Avatar(0)) { return 0; } return _stakingToken.balanceOf(address(avatar)); } function getTotalReputationSupply(bytes32 _proposalId) external view returns(uint256) { ProposalInfo memory proposal = proposalsInfo[msg.sender][_proposalId]; if (proposal.avatar == Avatar(0)) { return 0; } return proposal.avatar.nativeReputation().totalSupplyAt(proposal.blockNumber); } function reputationOf(address _owner, bytes32 _proposalId) external view returns(uint256) { ProposalInfo memory proposal = proposalsInfo[msg.sender][_proposalId]; if (proposal.avatar == Avatar(0)) { return 0; } return proposal.avatar.nativeReputation().balanceOfAt(_owner, proposal.blockNumber); } } // File: contracts/universalSchemes/ContributionReward.sol pragma solidity ^0.5.4; /** * @title A scheme for proposing and rewarding contributions to an organization * @dev An agent can ask an organization to recognize a contribution and reward * him with token, reputation, ether or any combination. */ contract ContributionReward is UniversalScheme, VotingMachineCallbacks, ProposalExecuteInterface { using SafeMath for uint; event NewContributionProposal( address indexed _avatar, bytes32 indexed _proposalId, address indexed _intVoteInterface, string _descriptionHash, int256 _reputationChange, uint[5] _rewards, IERC20 _externalToken, address _beneficiary ); event ProposalExecuted(address indexed _avatar, bytes32 indexed _proposalId, int256 _param); event RedeemReputation( address indexed _avatar, bytes32 indexed _proposalId, address indexed _beneficiary, int256 _amount); event RedeemEther(address indexed _avatar, bytes32 indexed _proposalId, address indexed _beneficiary, uint256 _amount); event RedeemNativeToken(address indexed _avatar, bytes32 indexed _proposalId, address indexed _beneficiary, uint256 _amount); event RedeemExternalToken(address indexed _avatar, bytes32 indexed _proposalId, address indexed _beneficiary, uint256 _amount); // A struct holding the data for a contribution proposal struct ContributionProposal { uint256 nativeTokenReward; // Reward asked in the native token of the organization. int256 reputationChange; // Organization reputation reward requested. uint256 ethReward; IERC20 externalToken; uint256 externalTokenReward; address payable beneficiary; uint256 periodLength; uint256 numberOfPeriods; uint256 executionTime; uint[4] redeemedPeriods; } // A mapping from the organization (Avatar) address to the saved data of the organization: mapping(address=>mapping(bytes32=>ContributionProposal)) public organizationsProposals; // A mapping from hashes to parameters (use to store a particular configuration on the controller) struct Parameters { bytes32 voteApproveParams; IntVoteInterface intVote; } // A mapping from hashes to parameters (use to store a particular configuration on the controller) mapping(bytes32=>Parameters) public parameters; /** * @dev execution of proposals, can only be called by the voting machine in which the vote is held. * @param _proposalId the ID of the voting in the voting machine * @param _param a parameter of the voting result, 1 yes and 2 is no. */ function executeProposal(bytes32 _proposalId, int256 _param) external onlyVotingMachine(_proposalId) returns(bool) { ProposalInfo memory proposal = proposalsInfo[msg.sender][_proposalId]; require(organizationsProposals[address(proposal.avatar)][_proposalId].executionTime == 0); require(organizationsProposals[address(proposal.avatar)][_proposalId].beneficiary != address(0)); // Check if vote was successful: if (_param == 1) { // solhint-disable-next-line not-rely-on-time organizationsProposals[address(proposal.avatar)][_proposalId].executionTime = now; } emit ProposalExecuted(address(proposal.avatar), _proposalId, _param); return true; } /** * @dev hash the parameters, save them if necessary, and return the hash value */ function setParameters( bytes32 _voteApproveParams, IntVoteInterface _intVote ) public returns(bytes32) { bytes32 paramsHash = getParametersHash( _voteApproveParams, _intVote ); parameters[paramsHash].voteApproveParams = _voteApproveParams; parameters[paramsHash].intVote = _intVote; return paramsHash; } /** * @dev return a hash of the given parameters * @param _voteApproveParams parameters for the voting machine used to approve a contribution * @param _intVote the voting machine used to approve a contribution * @return a hash of the parameters */ function getParametersHash( bytes32 _voteApproveParams, IntVoteInterface _intVote ) public pure returns(bytes32) { return (keccak256(abi.encodePacked(_voteApproveParams, _intVote))); } /** * @dev Submit a proposal for a reward for a contribution: * @param _avatar Avatar of the organization that the contribution was made for * @param _descriptionHash A hash of the proposal's description * @param _reputationChange - Amount of reputation change requested .Can be negative. * @param _rewards rewards array: * rewards[0] - Amount of tokens requested per period * rewards[1] - Amount of ETH requested per period * rewards[2] - Amount of external tokens requested per period * rewards[3] - Period length - if set to zero it allows immediate redeeming after execution. * rewards[4] - Number of periods * @param _externalToken Address of external token, if reward is requested there * @param _beneficiary Who gets the rewards */ function proposeContributionReward( Avatar _avatar, string memory _descriptionHash, int256 _reputationChange, uint[5] memory _rewards, IERC20 _externalToken, address payable _beneficiary ) public returns(bytes32) { validateProposalParams(_reputationChange, _rewards); Parameters memory controllerParams = parameters[getParametersFromController(_avatar)]; bytes32 contributionId = controllerParams.intVote.propose( 2, controllerParams.voteApproveParams, msg.sender, address(_avatar) ); address payable beneficiary = _beneficiary; if (beneficiary == address(0)) { beneficiary = msg.sender; } ContributionProposal memory proposal = ContributionProposal({ nativeTokenReward: _rewards[0], reputationChange: _reputationChange, ethReward: _rewards[1], externalToken: _externalToken, externalTokenReward: _rewards[2], beneficiary: beneficiary, periodLength: _rewards[3], numberOfPeriods: _rewards[4], executionTime: 0, redeemedPeriods:[uint(0), uint(0), uint(0), uint(0)] }); organizationsProposals[address(_avatar)][contributionId] = proposal; emit NewContributionProposal( address(_avatar), contributionId, address(controllerParams.intVote), _descriptionHash, _reputationChange, _rewards, _externalToken, beneficiary ); proposalsInfo[address(controllerParams.intVote)][contributionId] = ProposalInfo({ blockNumber:block.number, avatar:_avatar }); return contributionId; } /** * @dev RedeemReputation reward for proposal * @param _proposalId the ID of the voting in the voting machine * @param _avatar address of the controller * @return reputation the redeemed reputation. */ function redeemReputation(bytes32 _proposalId, Avatar _avatar) public returns(int256 reputation) { ContributionProposal memory _proposal = organizationsProposals[address(_avatar)][_proposalId]; ContributionProposal storage proposal = organizationsProposals[address(_avatar)][_proposalId]; require(proposal.executionTime != 0); uint256 periodsToPay = getPeriodsToPay(_proposalId, address(_avatar), 0); //set proposal reward to zero to prevent reentrancy attack. proposal.reputationChange = 0; reputation = int(periodsToPay) * _proposal.reputationChange; if (reputation > 0) { require( ControllerInterface( _avatar.owner()).mintReputation(uint(reputation), _proposal.beneficiary, address(_avatar))); } else if (reputation < 0) { require( ControllerInterface( _avatar.owner()).burnReputation(uint(reputation*(-1)), _proposal.beneficiary, address(_avatar))); } if (reputation != 0) { proposal.redeemedPeriods[0] = proposal.redeemedPeriods[0].add(periodsToPay); emit RedeemReputation(address(_avatar), _proposalId, _proposal.beneficiary, reputation); } //restore proposal reward. proposal.reputationChange = _proposal.reputationChange; } /** * @dev RedeemNativeToken reward for proposal * @param _proposalId the ID of the voting in the voting machine * @param _avatar address of the controller * @return amount the redeemed nativeToken. */ function redeemNativeToken(bytes32 _proposalId, Avatar _avatar) public returns(uint256 amount) { ContributionProposal memory _proposal = organizationsProposals[address(_avatar)][_proposalId]; ContributionProposal storage proposal = organizationsProposals[address(_avatar)][_proposalId]; require(proposal.executionTime != 0); uint256 periodsToPay = getPeriodsToPay(_proposalId, address(_avatar), 1); //set proposal rewards to zero to prevent reentrancy attack. proposal.nativeTokenReward = 0; amount = periodsToPay.mul(_proposal.nativeTokenReward); if (amount > 0) { require(ControllerInterface(_avatar.owner()).mintTokens(amount, _proposal.beneficiary, address(_avatar))); proposal.redeemedPeriods[1] = proposal.redeemedPeriods[1].add(periodsToPay); emit RedeemNativeToken(address(_avatar), _proposalId, _proposal.beneficiary, amount); } //restore proposal reward. proposal.nativeTokenReward = _proposal.nativeTokenReward; } /** * @dev RedeemEther reward for proposal * @param _proposalId the ID of the voting in the voting machine * @param _avatar address of the controller * @return amount ether redeemed amount */ function redeemEther(bytes32 _proposalId, Avatar _avatar) public returns(uint256 amount) { ContributionProposal memory _proposal = organizationsProposals[address(_avatar)][_proposalId]; ContributionProposal storage proposal = organizationsProposals[address(_avatar)][_proposalId]; require(proposal.executionTime != 0); uint256 periodsToPay = getPeriodsToPay(_proposalId, address(_avatar), 2); //set proposal rewards to zero to prevent reentrancy attack. proposal.ethReward = 0; amount = periodsToPay.mul(_proposal.ethReward); if (amount > 0) { require(ControllerInterface(_avatar.owner()).sendEther(amount, _proposal.beneficiary, _avatar)); proposal.redeemedPeriods[2] = proposal.redeemedPeriods[2].add(periodsToPay); emit RedeemEther(address(_avatar), _proposalId, _proposal.beneficiary, amount); } //restore proposal reward. proposal.ethReward = _proposal.ethReward; } /** * @dev RedeemNativeToken reward for proposal * @param _proposalId the ID of the voting in the voting machine * @param _avatar address of the controller * @return amount the external token redeemed amount */ function redeemExternalToken(bytes32 _proposalId, Avatar _avatar) public returns(uint256 amount) { ContributionProposal memory _proposal = organizationsProposals[address(_avatar)][_proposalId]; ContributionProposal storage proposal = organizationsProposals[address(_avatar)][_proposalId]; require(proposal.executionTime != 0); uint256 periodsToPay = getPeriodsToPay(_proposalId, address(_avatar), 3); //set proposal rewards to zero to prevent reentrancy attack. proposal.externalTokenReward = 0; if (proposal.externalToken != IERC20(0) && _proposal.externalTokenReward > 0) { amount = periodsToPay.mul(_proposal.externalTokenReward); if (amount > 0) { require( ControllerInterface( _avatar.owner()) .externalTokenTransfer(_proposal.externalToken, _proposal.beneficiary, amount, _avatar)); proposal.redeemedPeriods[3] = proposal.redeemedPeriods[3].add(periodsToPay); emit RedeemExternalToken(address(_avatar), _proposalId, _proposal.beneficiary, amount); } } //restore proposal reward. proposal.externalTokenReward = _proposal.externalTokenReward; } /** * @dev redeem rewards for proposal * @param _proposalId the ID of the voting in the voting machine * @param _avatar address of the controller * @param _whatToRedeem whatToRedeem array: * whatToRedeem[0] - reputation * whatToRedeem[1] - nativeTokenReward * whatToRedeem[2] - Ether * whatToRedeem[3] - ExternalToken * @return result boolean array for each redeem type. */ function redeem(bytes32 _proposalId, Avatar _avatar, bool[4] memory _whatToRedeem) public returns(int256 reputationReward, uint256 nativeTokenReward, uint256 etherReward, uint256 externalTokenReward) { if (_whatToRedeem[0]) { reputationReward = redeemReputation(_proposalId, _avatar); } if (_whatToRedeem[1]) { nativeTokenReward = redeemNativeToken(_proposalId, _avatar); } if (_whatToRedeem[2]) { etherReward = redeemEther(_proposalId, _avatar); } if (_whatToRedeem[3]) { externalTokenReward = redeemExternalToken(_proposalId, _avatar); } } /** * @dev getPeriodsToPay return the periods left to be paid for reputation,nativeToken,ether or externalToken. * The function ignore the reward amount to be paid (which can be zero). * @param _proposalId the ID of the voting in the voting machine * @param _avatar address of the controller * @param _redeemType - the type of the reward : * 0 - reputation * 1 - nativeTokenReward * 2 - Ether * 3 - ExternalToken * @return periods left to be paid. */ function getPeriodsToPay(bytes32 _proposalId, address _avatar, uint256 _redeemType) public view returns (uint256) { require(_redeemType <= 3, "should be in the redeemedPeriods range"); ContributionProposal memory _proposal = organizationsProposals[_avatar][_proposalId]; if (_proposal.executionTime == 0) return 0; uint256 periodsFromExecution; if (_proposal.periodLength > 0) { // solhint-disable-next-line not-rely-on-time periodsFromExecution = (now.sub(_proposal.executionTime))/(_proposal.periodLength); } uint256 periodsToPay; if ((_proposal.periodLength == 0) || (periodsFromExecution >= _proposal.numberOfPeriods)) { periodsToPay = _proposal.numberOfPeriods.sub(_proposal.redeemedPeriods[_redeemType]); } else { periodsToPay = periodsFromExecution.sub(_proposal.redeemedPeriods[_redeemType]); } return periodsToPay; } /** * @dev getRedeemedPeriods return the already redeemed periods for reputation, nativeToken, ether or externalToken. * @param _proposalId the ID of the voting in the voting machine * @param _avatar address of the controller * @param _redeemType - the type of the reward : * 0 - reputation * 1 - nativeTokenReward * 2 - Ether * 3 - ExternalToken * @return redeemed period. */ function getRedeemedPeriods(bytes32 _proposalId, address _avatar, uint256 _redeemType) public view returns (uint256) { return organizationsProposals[_avatar][_proposalId].redeemedPeriods[_redeemType]; } function getProposalEthReward(bytes32 _proposalId, address _avatar) public view returns (uint256) { return organizationsProposals[_avatar][_proposalId].ethReward; } function getProposalExternalTokenReward(bytes32 _proposalId, address _avatar) public view returns (uint256) { return organizationsProposals[_avatar][_proposalId].externalTokenReward; } function getProposalExternalToken(bytes32 _proposalId, address _avatar) public view returns (address) { return address(organizationsProposals[_avatar][_proposalId].externalToken); } function getProposalExecutionTime(bytes32 _proposalId, address _avatar) public view returns (uint256) { return organizationsProposals[_avatar][_proposalId].executionTime; } /** * @dev validateProposalParams validate proposal's rewards parameters. * The function check for potential overflow upon proposal's redeem. * The function reverts if the params are not valid. * @param _reputationChange - Amount of reputation change requested .Can be negative. * @param _rewards rewards array: * rewards[0] - Amount of tokens requested per period * rewards[1] - Amount of ETH requested per period * rewards[2] - Amount of external tokens requested per period * rewards[3] - Period length - if set to zero it allows immediate redeeming after execution. * rewards[4] - Number of periods */ function validateProposalParams(int256 _reputationChange, uint[5] memory _rewards) private pure { require(((_rewards[3] > 0) || (_rewards[4] == 1)), "periodLength equal 0 require numberOfPeriods to be 1"); if (_rewards[4] > 0) { // This is the only case of overflow not detected by the check below require(!(int(_rewards[4]) == -1 && _reputationChange == (-2**255)), "numberOfPeriods * _reputationChange will overflow"); //check that numberOfPeriods * _reputationChange will not overflow require((int(_rewards[4]) * _reputationChange) / int(_rewards[4]) == _reputationChange, "numberOfPeriods * reputationChange will overflow"); //check that numberOfPeriods * tokenReward will not overflow require((_rewards[4] * _rewards[0]) / _rewards[4] == _rewards[0], "numberOfPeriods * tokenReward will overflow"); //check that numberOfPeriods * ethReward will not overflow require((_rewards[4] * _rewards[1]) / _rewards[4] == _rewards[1], "numberOfPeriods * ethReward will overflow"); //check that numberOfPeriods * texternalTokenReward will not overflow require((_rewards[4] * _rewards[2]) / _rewards[4] == _rewards[2], "numberOfPeriods * texternalTokenReward will overflow"); } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"parameters","outputs":[{"name":"voteApproveParams","type":"bytes32"},{"name":"intVote","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"bytes32"}],"name":"organizationsProposals","outputs":[{"name":"nativeTokenReward","type":"uint256"},{"name":"reputationChange","type":"int256"},{"name":"ethReward","type":"uint256"},{"name":"externalToken","type":"address"},{"name":"externalTokenReward","type":"uint256"},{"name":"beneficiary","type":"address"},{"name":"periodLength","type":"uint256"},{"name":"numberOfPeriods","type":"uint256"},{"name":"executionTime","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"}],"name":"redeemReputation","outputs":[{"name":"reputation","type":"int256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"}],"name":"getProposalExternalTokenReward","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_voteApproveParams","type":"bytes32"},{"name":"_intVote","type":"address"}],"name":"getParametersHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"}],"name":"getProposalExecutionTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"}],"name":"getProposalEthReward","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"bytes32"}],"name":"proposalsInfo","outputs":[{"name":"blockNumber","type":"uint256"},{"name":"avatar","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_voteApproveParams","type":"bytes32"},{"name":"_intVote","type":"address"}],"name":"setParameters","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_stakingToken","type":"address"},{"name":"_proposalId","type":"bytes32"}],"name":"balanceOfStakingToken","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_avatar","type":"address"},{"name":"_descriptionHash","type":"string"},{"name":"_reputationChange","type":"int256"},{"name":"_rewards","type":"uint256[5]"},{"name":"_externalToken","type":"address"},{"name":"_beneficiary","type":"address"}],"name":"proposeContributionReward","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_proposalId","type":"bytes32"}],"name":"reputationOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_param","type":"int256"}],"name":"executeProposal","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_proposalId","type":"bytes32"}],"name":"getTotalReputationSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"},{"name":"_redeemType","type":"uint256"}],"name":"getRedeemedPeriods","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"}],"name":"redeemNativeToken","outputs":[{"name":"amount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_stakingToken","type":"address"},{"name":"_beneficiary","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_proposalId","type":"bytes32"}],"name":"stakingTokenTransfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"}],"name":"redeemEther","outputs":[{"name":"amount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"},{"name":"_beneficiary","type":"address"},{"name":"_proposalId","type":"bytes32"}],"name":"mintReputation","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"},{"name":"_whatToRedeem","type":"bool[4]"}],"name":"redeem","outputs":[{"name":"reputationReward","type":"int256"},{"name":"nativeTokenReward","type":"uint256"},{"name":"etherReward","type":"uint256"},{"name":"externalTokenReward","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"},{"name":"_redeemType","type":"uint256"}],"name":"getPeriodsToPay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"}],"name":"redeemExternalToken","outputs":[{"name":"amount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_proposalId","type":"bytes32"},{"name":"_avatar","type":"address"}],"name":"getProposalExternalToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"},{"name":"_beneficiary","type":"address"},{"name":"_proposalId","type":"bytes32"}],"name":"burnReputation","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_avatar","type":"address"},{"indexed":true,"name":"_proposalId","type":"bytes32"},{"indexed":true,"name":"_intVoteInterface","type":"address"},{"indexed":false,"name":"_descriptionHash","type":"string"},{"indexed":false,"name":"_reputationChange","type":"int256"},{"indexed":false,"name":"_rewards","type":"uint256[5]"},{"indexed":false,"name":"_externalToken","type":"address"},{"indexed":false,"name":"_beneficiary","type":"address"}],"name":"NewContributionProposal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_avatar","type":"address"},{"indexed":true,"name":"_proposalId","type":"bytes32"},{"indexed":false,"name":"_param","type":"int256"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_avatar","type":"address"},{"indexed":true,"name":"_proposalId","type":"bytes32"},{"indexed":true,"name":"_beneficiary","type":"address"},{"indexed":false,"name":"_amount","type":"int256"}],"name":"RedeemReputation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_avatar","type":"address"},{"indexed":true,"name":"_proposalId","type":"bytes32"},{"indexed":true,"name":"_beneficiary","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"RedeemEther","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_avatar","type":"address"},{"indexed":true,"name":"_proposalId","type":"bytes32"},{"indexed":true,"name":"_beneficiary","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"RedeemNativeToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_avatar","type":"address"},{"indexed":true,"name":"_proposalId","type":"bytes32"},{"indexed":true,"name":"_beneficiary","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"RedeemExternalToken","type":"event"}]
Contract Creation Code
608060405234801561001057600080fd5b50612d9c806100206000396000f3fe608060405234801561001057600080fd5b506004361061015c5760003560e060020a900480639d4c162d116100c7578063d29b5d2f11610080578063d29b5d2f146105d6578063d58bf09a14610608578063e074ee5514610691578063e63b681e146106c3578063f70bbb9a146106ef578063f81f8bf6146107375761015c565b80639d4c162d146104bc578063b551c373146104f3578063b7c251c314610510578063bb1c935114610542578063bea75f281461056e578063cd3ce306146105aa5761015c565b80636046f71d116101195780636046f71d146102e157806360bdbb3f1461030d57806368e14dac146103395780636b8eb40314610365578063896488b9146103915780639588378e146104905761015c565b8063025068041461016157806306e3a9781461019f5780630d5e1e821461021f5780631c3a57131461025d5780632453732a146102895780633a256daa146102b5575b600080fd5b61017e6004803603602081101561017757600080fd5b5035610769565b60408051928352600160a060020a0390911660208301528051918290030190f35b6101cb600480360360408110156101b557600080fd5b50600160a060020a03813516906020013561078b565b60408051998a5260208a019890985288880196909652600160a060020a0394851660608901526080880193909352921660a086015260c085019190915260e084015261010083015251908190036101200190f35b61024b6004803603604081101561023557600080fd5b5080359060200135600160a060020a03166107e9565b60408051918252519081900360200190f35b61024b6004803603604081101561027357600080fd5b5080359060200135600160a060020a0316610bdc565b61024b6004803603604081101561029f57600080fd5b5080359060200135600160a060020a0316610c0a565b61024b600480360360408110156102cb57600080fd5b5080359060200135600160a060020a0316610c4f565b61024b600480360360408110156102f757600080fd5b5080359060200135600160a060020a0316610c77565b61017e6004803603604081101561032357600080fd5b50600160a060020a038135169060200135610c9f565b61024b6004803603604081101561034f57600080fd5b5080359060200135600160a060020a0316610cc9565b61024b6004803603604081101561037b57600080fd5b50600160a060020a038135169060200135610d1b565b61024b60048036036101408110156103a857600080fd5b600160a060020a0382351691908101906040810160208201356401000000008111156103d357600080fd5b8201836020820111156103e557600080fd5b8035906020019184600183028401116401000000008311171561040757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805160a081810190925293968535969095909460c082019450925060200190600590839083908082843760009201919091525091945050508035600160a060020a03908116925060209091013516610dde565b61024b600480360360408110156104a657600080fd5b50600160a060020a038135169060200135611201565b6104df600480360360408110156104d257600080fd5b508035906020013561132d565b604080519115158252519081900360200190f35b61024b6004803603602081101561050957600080fd5b50356114b7565b61024b6004803603606081101561052657600080fd5b50803590600160a060020a03602082013516906040013561160f565b61024b6004803603604081101561055857600080fd5b5080359060200135600160a060020a031661164c565b6104df6004803603608081101561058457600080fd5b50600160a060020a03813581169160208101359091169060408101359060600135611907565b61024b600480360360408110156105c057600080fd5b5080359060200135600160a060020a0316611ac5565b6104df600480360360608110156105ec57600080fd5b50803590600160a060020a036020820135169060400135611d8e565b61066b600480360360c081101561061e57600080fd5b6040805160808181018352843594600160a060020a0360208201351694810193909260c084019290918401906004908390839080828437600092019190915250919450611f439350505050565b604080519485526020850193909352838301919091526060830152519081900360800190f35b61024b600480360360608110156106a757600080fd5b50803590600160a060020a036020820135169060400135611faf565b61024b600480360360408110156106d957600080fd5b5080359060200135600160a060020a0316612195565b61071b6004803603604081101561070557600080fd5b5080359060200135600160a060020a031661248f565b60408051600160a060020a039092168252519081900360200190f35b6104df6004803603606081101561074d57600080fd5b50803590600160a060020a0360208201351690604001356124bd565b60026020526000908152604090208054600190910154600160a060020a031682565b6001602081815260009384526040808520909152918352912080549181015460028201546003830154600484015460058501546006860154600787015460089097015495969495600160a060020a0394851695939490921692909189565b60006107f3612b11565b600160a060020a038381166000908152600160208181526040808420898552825292839020835161014081018552815481529281015491830191909152600281015482840152600381015484166060830152600480820154608080850191909152600583015490951660a0840152600682015460c0840152600782015460e0840152600882015461010084015283519485019384905291939092610120850192600985019182845b81548152602001906001019080831161089b5750505091909252505050600160a060020a0384166000908152600160209081526040808320888452909152902060088101549192509015156108ef57600080fd5b60006108fd86866000611faf565b600060018401819055602085015182029550909150841315610a365784600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561095557600080fd5b505afa158015610969573d6000803e3d6000fd5b505050506040513d602081101561097f57600080fd5b505160a0840151604080517feaf994b200000000000000000000000000000000000000000000000000000000815260048101889052600160a060020a03928316602482015288831660448201529051919092169163eaf994b29160648083019260209291908290030181600087803b1580156109fa57600080fd5b505af1158015610a0e573d6000803e3d6000fd5b505050506040513d6020811015610a2457600080fd5b50511515610a3157600080fd5b610b5a565b6000841215610b5a5784600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b158015610a7b57600080fd5b505afa158015610a8f573d6000803e3d6000fd5b505050506040513d6020811015610aa557600080fd5b505160a0840151604080517f6e94d27800000000000000000000000000000000000000000000000000000000815260008881036004830152600160a060020a039384166024830152898416604483015291519290931692636e94d2789260648083019360209383900390910190829087803b158015610b2357600080fd5b505af1158015610b37573d6000803e3d6000fd5b505050506040513d6020811015610b4d57600080fd5b50511515610b5a57600080fd5b8315610bc957610b79816009840160005b01549063ffffffff61263a16565b600983015560a0830151604080518681529051600160a060020a03928316928992908916917feab8bc4bf2fd6ce5634b8e75023e0e48367e68249ce2aa2c0ef7c0efe5648bee9181900360200190a45b5060209091015160019091015592915050565b600160a060020a03811660009081526001602090815260408083208584529091529020600401545b92915050565b60408051602080820194909452600160a060020a03929092166c0100000000000000000000000002828201528051808303603401815260549092019052805191012090565b600160a060020a03166000908152600160209081526040808320938352929052206008015490565b600160a060020a03166000908152600160209081526040808320938352929052206002015490565b600060208181529281526040808220909352908152208054600190910154600160a060020a031682565b600080610cd68484610c0a565b60008181526002602052604090208581556001018054600160a060020a03861673ffffffffffffffffffffffffffffffffffffffff1990911617905591505092915050565b33600090815260208181526040808320848452909152812060010154600160a060020a0316801515610d51576000915050610c04565b83600160a060020a03166370a08231826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200191505060206040518083038186803b158015610daa57600080fd5b505afa158015610dbe573d6000803e3d6000fd5b505050506040513d6020811015610dd457600080fd5b5051949350505050565b6000610dea858561264c565b610df2612b7c565b60026000610dff8a612879565b815260208082019290925260409081016000908120825180840184528154808252600190920154600160a060020a0390811682870181905285517f88737b5e000000000000000000000000000000000000000000000000000000008152600260048201526024810194909452336044850152908e166064840152935190955091936388737b5e9260848084019382900301818787803b158015610ea157600080fd5b505af1158015610eb5573d6000803e3d6000fd5b505050506040513d6020811015610ecb57600080fd5b5051905083600160a060020a0381161515610ee35750335b610eeb612b11565b60408051610140810182528951815260208082018c90528a015181830152600160a060020a038981166060830152918a0151608082015290831660a082015260c081018960036020908102919091015182520189600460200201518152602001600081526020016080604051908101604052806000815260200160008152602001600081526020016000815250815250905080600160008d600160a060020a0316600160a060020a03168152602001908152602001600020600085815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a815481600160a060020a030219169083600160a060020a031602179055506080820151816004015560a08201518160050160006101000a815481600160a060020a030219169083600160a060020a0316021790555060c0820151816006015560e0820151816007015561010082015181600801556101208201518160090190600461106d929190612b93565b509050508360200151600160a060020a0316838c600160a060020a03167fcbdcbf9aaeb1e9eff0f75d74e1c1e044bc87110164baec7d18d825b0450d97df8d8d8d8d89604051808060200186815260200185600560200280838360005b838110156110e25781810151838201526020016110ca565b5050505090500184600160a060020a0316600160a060020a0316815260200183600160a060020a0316600160a060020a03168152602001828103825287818151815260200191508051906020019080838360005b8381101561114e578181015183820152602001611136565b50505050905090810190601f16801561117b5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a45050604080518082018252438152600160a060020a039a8b166020808301918252948501518c1660009081528086528381208582529095529190932092518355516001909201805473ffffffffffffffffffffffffffffffffffffffff19169290991691909117909755509495945050505050565b600061120b612b7c565b503360009081526020818152604080832085845282529182902082518084019093528054835260010154600160a060020a03169082018190521515611254576000915050610c04565b8060200151600160a060020a03166389ae1c906040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561129457600080fd5b505afa1580156112a8573d6000803e3d6000fd5b505050506040513d60208110156112be57600080fd5b50518151604080517f4ee2cd7e000000000000000000000000000000000000000000000000000000008152600160a060020a038881166004830152602482019390935290519190921691634ee2cd7e916044808301926020929190829003018186803b158015610daa57600080fd5b336000908152602081815260408083208584529091528120600101548390600160a060020a03161515611398576040805160e560020a62461bcd0281526020600482015260126024820152600080516020612c42833981519152604482015290519081900360640190fd5b6113a0612b7c565b503360009081526020818152604080832087845282528083208151808301835281548152600191820154600160a060020a0316818501819052855290835281842088855290925290912060080154156113f857600080fd5b602080820151600160a060020a039081166000908152600183526040808220898352909352919091206005015416151561143157600080fd5b836001141561146657602080820151600160a060020a0316600090815260018252604080822088835290925220426008909101555b848160200151600160a060020a03167fd2632e80f5364f02aded1c64e8a04637b7c8bb9c2db2bedf4b6ac47c013acbc0866040518082815260200191505060405180910390a3506001949350505050565b60006114c1612b7c565b503360009081526020818152604080832085845282529182902082518084019093528054835260010154600160a060020a0316908201819052151561150a57600091505061160a565b8060200151600160a060020a03166389ae1c906040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561154a57600080fd5b505afa15801561155e573d6000803e3d6000fd5b505050506040513d602081101561157457600080fd5b50518151604080517f981b24d0000000000000000000000000000000000000000000000000000000008152600481019290925251600160a060020a039092169163981b24d091602480820192602092909190829003018186803b1580156115da57600080fd5b505afa1580156115ee573d6000803e3d6000fd5b505050506040513d602081101561160457600080fd5b50519150505b919050565b600160a060020a03821660009081526001602090815260408083208684529091528120600901826004811061164057fe5b015490505b9392505050565b6000611656612b11565b600160a060020a038381166000908152600160208181526040808420898552825292839020835161014081018552815481529281015491830191909152600281015482840152600381015484166060830152600480820154608080850191909152600583015490951660a0840152600682015460c0840152600782015460e0840152600882015461010084015283519485019384905291939092610120850192600985019182845b8154815260200190600101908083116116fe5750505091909252505050600160a060020a03841660009081526001602090815260408083208884529091529020600881015491925090151561175257600080fd5b600061176086866001611faf565b60008355835190915061177a90829063ffffffff612ad116565b935060008411156118fc5784600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156117c157600080fd5b505afa1580156117d5573d6000803e3d6000fd5b505050506040513d60208110156117eb57600080fd5b505160a0840151604080517f6407e43200000000000000000000000000000000000000000000000000000000815260048101889052600160a060020a039283166024820152888316604482015290519190921691636407e4329160648083019260209291908290030181600087803b15801561186657600080fd5b505af115801561187a573d6000803e3d6000fd5b505050506040513d602081101561189057600080fd5b5051151561189d57600080fd5b6118ac81600984016001610b6b565b600a83015560a0830151604080518681529051600160a060020a03928316928992908916917f13f7471cab9806ac4ff5d80ae879babfbf1081e240d05c4450b75f69c626cb2e9181900360200190a45b509051905592915050565b336000908152602081815260408083208484529091528120600101548290600160a060020a03161515611972576040805160e560020a62461bcd0281526020600482015260126024820152600080516020612c42833981519152604482015290519081900360640190fd5b33600090815260208181526040808320868452909152902060010154600160a060020a03168015156119a8576000925050611abc565b80600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156119e457600080fd5b505afa1580156119f8573d6000803e3d6000fd5b505050506040513d6020811015611a0e57600080fd5b5051604080517fb9a04cdd000000000000000000000000000000000000000000000000000000008152600160a060020a038a8116600483015289811660248301526044820189905284811660648301529151919092169163b9a04cdd9160848083019260209291908290030181600087803b158015611a8c57600080fd5b505af1158015611aa0573d6000803e3d6000fd5b505050506040513d6020811015611ab657600080fd5b50519250505b50949350505050565b6000611acf612b11565b600160a060020a038381166000908152600160208181526040808420898552825292839020835161014081018552815481529281015491830191909152600281015482840152600381015484166060830152600480820154608080850191909152600583015490951660a0840152600682015460c0840152600782015460e0840152600882015461010084015283519485019384905291939092610120850192600985019182845b815481526020019060010190808311611b775750505091909252505050600160a060020a038416600090815260016020908152604080832088845290915290206008810154919250901515611bcb57600080fd5b6000611bd986866002611faf565b600060028401556040840151909150611bf990829063ffffffff612ad116565b93506000841115611d7b5784600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b158015611c4057600080fd5b505afa158015611c54573d6000803e3d6000fd5b505050506040513d6020811015611c6a57600080fd5b505160a0840151604080517f634965da00000000000000000000000000000000000000000000000000000000815260048101889052600160a060020a03928316602482015288831660448201529051919092169163634965da9160648083019260209291908290030181600087803b158015611ce557600080fd5b505af1158015611cf9573d6000803e3d6000fd5b505050506040513d6020811015611d0f57600080fd5b50511515611d1c57600080fd5b611d2b81600984016002610b6b565b600b83015560a0830151604080518681529051600160a060020a03928316928992908916917f7dd55ea53ce2c347b544c257b778e1dd6638f232fa6b94320e740440e72b4b879181900360200190a45b5060409091015160029091015592915050565b336000908152602081815260408083208484529091528120600101548290600160a060020a03161515611df9576040805160e560020a62461bcd0281526020600482015260126024820152600080516020612c42833981519152604482015290519081900360640190fd5b33600090815260208181526040808320868452909152902060010154600160a060020a0316801515611e2f576000925050611f3b565b80600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b158015611e6b57600080fd5b505afa158015611e7f573d6000803e3d6000fd5b505050506040513d6020811015611e9557600080fd5b5051604080517feaf994b200000000000000000000000000000000000000000000000000000000815260048101899052600160a060020a03888116602483015284811660448301529151919092169163eaf994b29160648083019260209291908290030181600087803b158015611f0b57600080fd5b505af1158015611f1f573d6000803e3d6000fd5b505050506040513d6020811015611f3557600080fd5b50519250505b509392505050565b60008080808481602002015115611f6157611f5e87876107e9565b93505b602085015115611f7857611f75878761164c565b92505b604085015115611f8f57611f8c8787611ac5565b91505b606085015115611fa657611fa38787612195565b90505b93509350935093565b60006003821115611ff45760405160e560020a62461bcd028152600401808060200182810382526026815260200180612d176026913960400191505060405180910390fd5b611ffc612b11565b600160a060020a0384811660009081526001602081815260408084208a8552825292839020835161014081018552815481529281015491830191909152600281015482840152600381015484166060830152600480820154608080850191909152600583015490951660a0840152600682015460c0840152600782015460e0840152600882015461010084015283519485019384905291939092610120850192600985019182845b8154815260200190600101908083116120a4575050505050815250509050806101000151600014156120da576000915050611645565b6000808260c0015111156121115760c082015161010083015161210490429063ffffffff612afc16565b81151561210d57fe5b0490505b60008260c001516000148061212a57508260e001518210155b156121615761012083015161215a90866004811061214457fe5b602002015160e08501519063ffffffff612afc16565b905061218b565b61012083015161218890866004811061217657fe5b6020020151839063ffffffff612afc16565b90505b9695505050505050565b600061219f612b11565b600160a060020a038381166000908152600160208181526040808420898552825292839020835161014081018552815481529281015491830191909152600281015482840152600381015484166060830152600480820154608080850191909152600583015490951660a0840152600682015460c0840152600782015460e0840152600882015461010084015283519485019384905291939092610120850192600985019182845b8154815260200190600101908083116122475750505091909252505050600160a060020a03841660009081526001602090815260408083208884529091529020600881015491925090151561229b57600080fd5b60006122a986866003611faf565b600060048401556003830154909150600160a060020a0316158015906122d3575060008360800151115b1561247c5760808301516122ee90829063ffffffff612ad116565b9350600084111561247c5784600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561233557600080fd5b505afa158015612349573d6000803e3d6000fd5b505050506040513d602081101561235f57600080fd5b5051606084015160a0850151604080517fb9a04cdd000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201889052888316606483015251919092169163b9a04cdd9160848083019260209291908290030181600087803b1580156123e657600080fd5b505af11580156123fa573d6000803e3d6000fd5b505050506040513d602081101561241057600080fd5b5051151561241d57600080fd5b61242c81600984016003610b6b565b600c83015560a0830151604080518681529051600160a060020a03928316928992908916917f5a66e28cdcd3bc22082d9f07be2b6bed5f50f349e5d89f655d750ecdd19883749181900360200190a45b5060809091015160049091015592915050565b600160a060020a03908116600090815260016020908152604080832094835293905291909120600301541690565b336000908152602081815260408083208484529091528120600101548290600160a060020a03161515612528576040805160e560020a62461bcd0281526020600482015260126024820152600080516020612c42833981519152604482015290519081900360640190fd5b33600090815260208181526040808320868452909152902060010154600160a060020a031680151561255e576000925050611f3b565b80600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561259a57600080fd5b505afa1580156125ae573d6000803e3d6000fd5b505050506040513d60208110156125c457600080fd5b5051604080517f6e94d27800000000000000000000000000000000000000000000000000000000815260048101899052600160a060020a038881166024830152848116604483015291519190921691636e94d2789160648083019260209291908290030181600087803b158015611f0b57600080fd5b60008282018381101561164557600080fd5b606081015160001080612663575060808101516001145b15156126a35760405160e560020a62461bcd028152600401808060200182810382526034815260200180612c0e6034913960400191505060405180910390fd5b6080810151600010156128755760808101516000191480156126e45750817f8000000000000000000000000000000000000000000000000000000000000000145b156127235760405160e560020a62461bcd028152600401808060200182810382526031815260200180612ce66031913960400191505060405180910390fd5b6080810151829080820281151561273657fe5b05146127765760405160e560020a62461bcd028152600401808060200182810382526030815260200180612c8d6030913960400191505060405180910390fd5b8051608082015180820281151561278957fe5b04146127c95760405160e560020a62461bcd02815260040180806020018281038252602b815260200180612c62602b913960400191505060405180910390fd5b602081015160808201518082028115156127df57fe5b041461281f5760405160e560020a62461bcd028152600401808060200182810382526029815260200180612cbd6029913960400191505060405180910390fd5b6040810151608082015180820281151561283557fe5b04146128755760405160e560020a62461bcd028152600401808060200182810382526034815260200180612d3d6034913960400191505060405180910390fd5b5050565b600081600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156128b757600080fd5b505afa1580156128cb573d6000803e3d6000fd5b505050506040513d60208110156128e157600080fd5b5051604080517f9be2faed000000000000000000000000000000000000000000000000000000008152306004820152600160a060020a03858116602483015291519190921691639be2faed916044808301926020929190829003018186803b15801561294c57600080fd5b505afa158015612960573d6000803e3d6000fd5b505050506040513d602081101561297657600080fd5b505115156129ce576040805160e560020a62461bcd02815260206004820152601860248201527f736368656d65206973206e6f7420726567697374657265640000000000000000604482015290519081900360640190fd5b81600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b158015612a0a57600080fd5b505afa158015612a1e573d6000803e3d6000fd5b505050506040513d6020811015612a3457600080fd5b5051604080517f1c4d5608000000000000000000000000000000000000000000000000000000008152306004820152600160a060020a03858116602483015291519190921691631c4d5608916044808301926020929190829003018186803b158015612a9f57600080fd5b505afa158015612ab3573d6000803e3d6000fd5b505050506040513d6020811015612ac957600080fd5b505192915050565b6000821515612ae257506000610c04565b828202828482811515612af157fe5b041461164557600080fd5b600082821115612b0b57600080fd5b50900390565b6101a0604051908101604052806000815260200160008152602001600081526020016000600160a060020a03168152602001600081526020016000600160a060020a03168152602001600081526020016000815260200160008152602001612b77612bd1565b905290565b604080518082019091526000808252602082015290565b8260048101928215612bc1579160200282015b82811115612bc1578251825591602001919060010190612ba6565b50612bcd929150612bf0565b5090565b6080604051908101604052806004906020820280388339509192915050565b612c0a91905b80821115612bcd5760008155600101612bf6565b9056fe706572696f644c656e67746820657175616c20302072657175697265206e756d6265724f66506572696f647320746f20626520316f6e6c7920566f74696e674d616368696e6500000000000000000000000000006e756d6265724f66506572696f6473202a20746f6b656e5265776172642077696c6c206f766572666c6f776e756d6265724f66506572696f6473202a2072657075746174696f6e4368616e67652077696c6c206f766572666c6f776e756d6265724f66506572696f6473202a206574685265776172642077696c6c206f766572666c6f776e756d6265724f66506572696f6473202a205f72657075746174696f6e4368616e67652077696c6c206f766572666c6f7773686f756c6420626520696e207468652072656465656d6564506572696f64732072616e67656e756d6265724f66506572696f6473202a207465787465726e616c546f6b656e5265776172642077696c6c206f766572666c6f77a165627a7a723058200eb8c8f2cb6ec53f6a032eecf43b0ccb0d69df3f3600ccaf877298559cd547d50029
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061015c5760003560e060020a900480639d4c162d116100c7578063d29b5d2f11610080578063d29b5d2f146105d6578063d58bf09a14610608578063e074ee5514610691578063e63b681e146106c3578063f70bbb9a146106ef578063f81f8bf6146107375761015c565b80639d4c162d146104bc578063b551c373146104f3578063b7c251c314610510578063bb1c935114610542578063bea75f281461056e578063cd3ce306146105aa5761015c565b80636046f71d116101195780636046f71d146102e157806360bdbb3f1461030d57806368e14dac146103395780636b8eb40314610365578063896488b9146103915780639588378e146104905761015c565b8063025068041461016157806306e3a9781461019f5780630d5e1e821461021f5780631c3a57131461025d5780632453732a146102895780633a256daa146102b5575b600080fd5b61017e6004803603602081101561017757600080fd5b5035610769565b60408051928352600160a060020a0390911660208301528051918290030190f35b6101cb600480360360408110156101b557600080fd5b50600160a060020a03813516906020013561078b565b60408051998a5260208a019890985288880196909652600160a060020a0394851660608901526080880193909352921660a086015260c085019190915260e084015261010083015251908190036101200190f35b61024b6004803603604081101561023557600080fd5b5080359060200135600160a060020a03166107e9565b60408051918252519081900360200190f35b61024b6004803603604081101561027357600080fd5b5080359060200135600160a060020a0316610bdc565b61024b6004803603604081101561029f57600080fd5b5080359060200135600160a060020a0316610c0a565b61024b600480360360408110156102cb57600080fd5b5080359060200135600160a060020a0316610c4f565b61024b600480360360408110156102f757600080fd5b5080359060200135600160a060020a0316610c77565b61017e6004803603604081101561032357600080fd5b50600160a060020a038135169060200135610c9f565b61024b6004803603604081101561034f57600080fd5b5080359060200135600160a060020a0316610cc9565b61024b6004803603604081101561037b57600080fd5b50600160a060020a038135169060200135610d1b565b61024b60048036036101408110156103a857600080fd5b600160a060020a0382351691908101906040810160208201356401000000008111156103d357600080fd5b8201836020820111156103e557600080fd5b8035906020019184600183028401116401000000008311171561040757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805160a081810190925293968535969095909460c082019450925060200190600590839083908082843760009201919091525091945050508035600160a060020a03908116925060209091013516610dde565b61024b600480360360408110156104a657600080fd5b50600160a060020a038135169060200135611201565b6104df600480360360408110156104d257600080fd5b508035906020013561132d565b604080519115158252519081900360200190f35b61024b6004803603602081101561050957600080fd5b50356114b7565b61024b6004803603606081101561052657600080fd5b50803590600160a060020a03602082013516906040013561160f565b61024b6004803603604081101561055857600080fd5b5080359060200135600160a060020a031661164c565b6104df6004803603608081101561058457600080fd5b50600160a060020a03813581169160208101359091169060408101359060600135611907565b61024b600480360360408110156105c057600080fd5b5080359060200135600160a060020a0316611ac5565b6104df600480360360608110156105ec57600080fd5b50803590600160a060020a036020820135169060400135611d8e565b61066b600480360360c081101561061e57600080fd5b6040805160808181018352843594600160a060020a0360208201351694810193909260c084019290918401906004908390839080828437600092019190915250919450611f439350505050565b604080519485526020850193909352838301919091526060830152519081900360800190f35b61024b600480360360608110156106a757600080fd5b50803590600160a060020a036020820135169060400135611faf565b61024b600480360360408110156106d957600080fd5b5080359060200135600160a060020a0316612195565b61071b6004803603604081101561070557600080fd5b5080359060200135600160a060020a031661248f565b60408051600160a060020a039092168252519081900360200190f35b6104df6004803603606081101561074d57600080fd5b50803590600160a060020a0360208201351690604001356124bd565b60026020526000908152604090208054600190910154600160a060020a031682565b6001602081815260009384526040808520909152918352912080549181015460028201546003830154600484015460058501546006860154600787015460089097015495969495600160a060020a0394851695939490921692909189565b60006107f3612b11565b600160a060020a038381166000908152600160208181526040808420898552825292839020835161014081018552815481529281015491830191909152600281015482840152600381015484166060830152600480820154608080850191909152600583015490951660a0840152600682015460c0840152600782015460e0840152600882015461010084015283519485019384905291939092610120850192600985019182845b81548152602001906001019080831161089b5750505091909252505050600160a060020a0384166000908152600160209081526040808320888452909152902060088101549192509015156108ef57600080fd5b60006108fd86866000611faf565b600060018401819055602085015182029550909150841315610a365784600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561095557600080fd5b505afa158015610969573d6000803e3d6000fd5b505050506040513d602081101561097f57600080fd5b505160a0840151604080517feaf994b200000000000000000000000000000000000000000000000000000000815260048101889052600160a060020a03928316602482015288831660448201529051919092169163eaf994b29160648083019260209291908290030181600087803b1580156109fa57600080fd5b505af1158015610a0e573d6000803e3d6000fd5b505050506040513d6020811015610a2457600080fd5b50511515610a3157600080fd5b610b5a565b6000841215610b5a5784600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b158015610a7b57600080fd5b505afa158015610a8f573d6000803e3d6000fd5b505050506040513d6020811015610aa557600080fd5b505160a0840151604080517f6e94d27800000000000000000000000000000000000000000000000000000000815260008881036004830152600160a060020a039384166024830152898416604483015291519290931692636e94d2789260648083019360209383900390910190829087803b158015610b2357600080fd5b505af1158015610b37573d6000803e3d6000fd5b505050506040513d6020811015610b4d57600080fd5b50511515610b5a57600080fd5b8315610bc957610b79816009840160005b01549063ffffffff61263a16565b600983015560a0830151604080518681529051600160a060020a03928316928992908916917feab8bc4bf2fd6ce5634b8e75023e0e48367e68249ce2aa2c0ef7c0efe5648bee9181900360200190a45b5060209091015160019091015592915050565b600160a060020a03811660009081526001602090815260408083208584529091529020600401545b92915050565b60408051602080820194909452600160a060020a03929092166c0100000000000000000000000002828201528051808303603401815260549092019052805191012090565b600160a060020a03166000908152600160209081526040808320938352929052206008015490565b600160a060020a03166000908152600160209081526040808320938352929052206002015490565b600060208181529281526040808220909352908152208054600190910154600160a060020a031682565b600080610cd68484610c0a565b60008181526002602052604090208581556001018054600160a060020a03861673ffffffffffffffffffffffffffffffffffffffff1990911617905591505092915050565b33600090815260208181526040808320848452909152812060010154600160a060020a0316801515610d51576000915050610c04565b83600160a060020a03166370a08231826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200191505060206040518083038186803b158015610daa57600080fd5b505afa158015610dbe573d6000803e3d6000fd5b505050506040513d6020811015610dd457600080fd5b5051949350505050565b6000610dea858561264c565b610df2612b7c565b60026000610dff8a612879565b815260208082019290925260409081016000908120825180840184528154808252600190920154600160a060020a0390811682870181905285517f88737b5e000000000000000000000000000000000000000000000000000000008152600260048201526024810194909452336044850152908e166064840152935190955091936388737b5e9260848084019382900301818787803b158015610ea157600080fd5b505af1158015610eb5573d6000803e3d6000fd5b505050506040513d6020811015610ecb57600080fd5b5051905083600160a060020a0381161515610ee35750335b610eeb612b11565b60408051610140810182528951815260208082018c90528a015181830152600160a060020a038981166060830152918a0151608082015290831660a082015260c081018960036020908102919091015182520189600460200201518152602001600081526020016080604051908101604052806000815260200160008152602001600081526020016000815250815250905080600160008d600160a060020a0316600160a060020a03168152602001908152602001600020600085815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a815481600160a060020a030219169083600160a060020a031602179055506080820151816004015560a08201518160050160006101000a815481600160a060020a030219169083600160a060020a0316021790555060c0820151816006015560e0820151816007015561010082015181600801556101208201518160090190600461106d929190612b93565b509050508360200151600160a060020a0316838c600160a060020a03167fcbdcbf9aaeb1e9eff0f75d74e1c1e044bc87110164baec7d18d825b0450d97df8d8d8d8d89604051808060200186815260200185600560200280838360005b838110156110e25781810151838201526020016110ca565b5050505090500184600160a060020a0316600160a060020a0316815260200183600160a060020a0316600160a060020a03168152602001828103825287818151815260200191508051906020019080838360005b8381101561114e578181015183820152602001611136565b50505050905090810190601f16801561117b5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a45050604080518082018252438152600160a060020a039a8b166020808301918252948501518c1660009081528086528381208582529095529190932092518355516001909201805473ffffffffffffffffffffffffffffffffffffffff19169290991691909117909755509495945050505050565b600061120b612b7c565b503360009081526020818152604080832085845282529182902082518084019093528054835260010154600160a060020a03169082018190521515611254576000915050610c04565b8060200151600160a060020a03166389ae1c906040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561129457600080fd5b505afa1580156112a8573d6000803e3d6000fd5b505050506040513d60208110156112be57600080fd5b50518151604080517f4ee2cd7e000000000000000000000000000000000000000000000000000000008152600160a060020a038881166004830152602482019390935290519190921691634ee2cd7e916044808301926020929190829003018186803b158015610daa57600080fd5b336000908152602081815260408083208584529091528120600101548390600160a060020a03161515611398576040805160e560020a62461bcd0281526020600482015260126024820152600080516020612c42833981519152604482015290519081900360640190fd5b6113a0612b7c565b503360009081526020818152604080832087845282528083208151808301835281548152600191820154600160a060020a0316818501819052855290835281842088855290925290912060080154156113f857600080fd5b602080820151600160a060020a039081166000908152600183526040808220898352909352919091206005015416151561143157600080fd5b836001141561146657602080820151600160a060020a0316600090815260018252604080822088835290925220426008909101555b848160200151600160a060020a03167fd2632e80f5364f02aded1c64e8a04637b7c8bb9c2db2bedf4b6ac47c013acbc0866040518082815260200191505060405180910390a3506001949350505050565b60006114c1612b7c565b503360009081526020818152604080832085845282529182902082518084019093528054835260010154600160a060020a0316908201819052151561150a57600091505061160a565b8060200151600160a060020a03166389ae1c906040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561154a57600080fd5b505afa15801561155e573d6000803e3d6000fd5b505050506040513d602081101561157457600080fd5b50518151604080517f981b24d0000000000000000000000000000000000000000000000000000000008152600481019290925251600160a060020a039092169163981b24d091602480820192602092909190829003018186803b1580156115da57600080fd5b505afa1580156115ee573d6000803e3d6000fd5b505050506040513d602081101561160457600080fd5b50519150505b919050565b600160a060020a03821660009081526001602090815260408083208684529091528120600901826004811061164057fe5b015490505b9392505050565b6000611656612b11565b600160a060020a038381166000908152600160208181526040808420898552825292839020835161014081018552815481529281015491830191909152600281015482840152600381015484166060830152600480820154608080850191909152600583015490951660a0840152600682015460c0840152600782015460e0840152600882015461010084015283519485019384905291939092610120850192600985019182845b8154815260200190600101908083116116fe5750505091909252505050600160a060020a03841660009081526001602090815260408083208884529091529020600881015491925090151561175257600080fd5b600061176086866001611faf565b60008355835190915061177a90829063ffffffff612ad116565b935060008411156118fc5784600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156117c157600080fd5b505afa1580156117d5573d6000803e3d6000fd5b505050506040513d60208110156117eb57600080fd5b505160a0840151604080517f6407e43200000000000000000000000000000000000000000000000000000000815260048101889052600160a060020a039283166024820152888316604482015290519190921691636407e4329160648083019260209291908290030181600087803b15801561186657600080fd5b505af115801561187a573d6000803e3d6000fd5b505050506040513d602081101561189057600080fd5b5051151561189d57600080fd5b6118ac81600984016001610b6b565b600a83015560a0830151604080518681529051600160a060020a03928316928992908916917f13f7471cab9806ac4ff5d80ae879babfbf1081e240d05c4450b75f69c626cb2e9181900360200190a45b509051905592915050565b336000908152602081815260408083208484529091528120600101548290600160a060020a03161515611972576040805160e560020a62461bcd0281526020600482015260126024820152600080516020612c42833981519152604482015290519081900360640190fd5b33600090815260208181526040808320868452909152902060010154600160a060020a03168015156119a8576000925050611abc565b80600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156119e457600080fd5b505afa1580156119f8573d6000803e3d6000fd5b505050506040513d6020811015611a0e57600080fd5b5051604080517fb9a04cdd000000000000000000000000000000000000000000000000000000008152600160a060020a038a8116600483015289811660248301526044820189905284811660648301529151919092169163b9a04cdd9160848083019260209291908290030181600087803b158015611a8c57600080fd5b505af1158015611aa0573d6000803e3d6000fd5b505050506040513d6020811015611ab657600080fd5b50519250505b50949350505050565b6000611acf612b11565b600160a060020a038381166000908152600160208181526040808420898552825292839020835161014081018552815481529281015491830191909152600281015482840152600381015484166060830152600480820154608080850191909152600583015490951660a0840152600682015460c0840152600782015460e0840152600882015461010084015283519485019384905291939092610120850192600985019182845b815481526020019060010190808311611b775750505091909252505050600160a060020a038416600090815260016020908152604080832088845290915290206008810154919250901515611bcb57600080fd5b6000611bd986866002611faf565b600060028401556040840151909150611bf990829063ffffffff612ad116565b93506000841115611d7b5784600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b158015611c4057600080fd5b505afa158015611c54573d6000803e3d6000fd5b505050506040513d6020811015611c6a57600080fd5b505160a0840151604080517f634965da00000000000000000000000000000000000000000000000000000000815260048101889052600160a060020a03928316602482015288831660448201529051919092169163634965da9160648083019260209291908290030181600087803b158015611ce557600080fd5b505af1158015611cf9573d6000803e3d6000fd5b505050506040513d6020811015611d0f57600080fd5b50511515611d1c57600080fd5b611d2b81600984016002610b6b565b600b83015560a0830151604080518681529051600160a060020a03928316928992908916917f7dd55ea53ce2c347b544c257b778e1dd6638f232fa6b94320e740440e72b4b879181900360200190a45b5060409091015160029091015592915050565b336000908152602081815260408083208484529091528120600101548290600160a060020a03161515611df9576040805160e560020a62461bcd0281526020600482015260126024820152600080516020612c42833981519152604482015290519081900360640190fd5b33600090815260208181526040808320868452909152902060010154600160a060020a0316801515611e2f576000925050611f3b565b80600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b158015611e6b57600080fd5b505afa158015611e7f573d6000803e3d6000fd5b505050506040513d6020811015611e9557600080fd5b5051604080517feaf994b200000000000000000000000000000000000000000000000000000000815260048101899052600160a060020a03888116602483015284811660448301529151919092169163eaf994b29160648083019260209291908290030181600087803b158015611f0b57600080fd5b505af1158015611f1f573d6000803e3d6000fd5b505050506040513d6020811015611f3557600080fd5b50519250505b509392505050565b60008080808481602002015115611f6157611f5e87876107e9565b93505b602085015115611f7857611f75878761164c565b92505b604085015115611f8f57611f8c8787611ac5565b91505b606085015115611fa657611fa38787612195565b90505b93509350935093565b60006003821115611ff45760405160e560020a62461bcd028152600401808060200182810382526026815260200180612d176026913960400191505060405180910390fd5b611ffc612b11565b600160a060020a0384811660009081526001602081815260408084208a8552825292839020835161014081018552815481529281015491830191909152600281015482840152600381015484166060830152600480820154608080850191909152600583015490951660a0840152600682015460c0840152600782015460e0840152600882015461010084015283519485019384905291939092610120850192600985019182845b8154815260200190600101908083116120a4575050505050815250509050806101000151600014156120da576000915050611645565b6000808260c0015111156121115760c082015161010083015161210490429063ffffffff612afc16565b81151561210d57fe5b0490505b60008260c001516000148061212a57508260e001518210155b156121615761012083015161215a90866004811061214457fe5b602002015160e08501519063ffffffff612afc16565b905061218b565b61012083015161218890866004811061217657fe5b6020020151839063ffffffff612afc16565b90505b9695505050505050565b600061219f612b11565b600160a060020a038381166000908152600160208181526040808420898552825292839020835161014081018552815481529281015491830191909152600281015482840152600381015484166060830152600480820154608080850191909152600583015490951660a0840152600682015460c0840152600782015460e0840152600882015461010084015283519485019384905291939092610120850192600985019182845b8154815260200190600101908083116122475750505091909252505050600160a060020a03841660009081526001602090815260408083208884529091529020600881015491925090151561229b57600080fd5b60006122a986866003611faf565b600060048401556003830154909150600160a060020a0316158015906122d3575060008360800151115b1561247c5760808301516122ee90829063ffffffff612ad116565b9350600084111561247c5784600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561233557600080fd5b505afa158015612349573d6000803e3d6000fd5b505050506040513d602081101561235f57600080fd5b5051606084015160a0850151604080517fb9a04cdd000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201889052888316606483015251919092169163b9a04cdd9160848083019260209291908290030181600087803b1580156123e657600080fd5b505af11580156123fa573d6000803e3d6000fd5b505050506040513d602081101561241057600080fd5b5051151561241d57600080fd5b61242c81600984016003610b6b565b600c83015560a0830151604080518681529051600160a060020a03928316928992908916917f5a66e28cdcd3bc22082d9f07be2b6bed5f50f349e5d89f655d750ecdd19883749181900360200190a45b5060809091015160049091015592915050565b600160a060020a03908116600090815260016020908152604080832094835293905291909120600301541690565b336000908152602081815260408083208484529091528120600101548290600160a060020a03161515612528576040805160e560020a62461bcd0281526020600482015260126024820152600080516020612c42833981519152604482015290519081900360640190fd5b33600090815260208181526040808320868452909152902060010154600160a060020a031680151561255e576000925050611f3b565b80600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561259a57600080fd5b505afa1580156125ae573d6000803e3d6000fd5b505050506040513d60208110156125c457600080fd5b5051604080517f6e94d27800000000000000000000000000000000000000000000000000000000815260048101899052600160a060020a038881166024830152848116604483015291519190921691636e94d2789160648083019260209291908290030181600087803b158015611f0b57600080fd5b60008282018381101561164557600080fd5b606081015160001080612663575060808101516001145b15156126a35760405160e560020a62461bcd028152600401808060200182810382526034815260200180612c0e6034913960400191505060405180910390fd5b6080810151600010156128755760808101516000191480156126e45750817f8000000000000000000000000000000000000000000000000000000000000000145b156127235760405160e560020a62461bcd028152600401808060200182810382526031815260200180612ce66031913960400191505060405180910390fd5b6080810151829080820281151561273657fe5b05146127765760405160e560020a62461bcd028152600401808060200182810382526030815260200180612c8d6030913960400191505060405180910390fd5b8051608082015180820281151561278957fe5b04146127c95760405160e560020a62461bcd02815260040180806020018281038252602b815260200180612c62602b913960400191505060405180910390fd5b602081015160808201518082028115156127df57fe5b041461281f5760405160e560020a62461bcd028152600401808060200182810382526029815260200180612cbd6029913960400191505060405180910390fd5b6040810151608082015180820281151561283557fe5b04146128755760405160e560020a62461bcd028152600401808060200182810382526034815260200180612d3d6034913960400191505060405180910390fd5b5050565b600081600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156128b757600080fd5b505afa1580156128cb573d6000803e3d6000fd5b505050506040513d60208110156128e157600080fd5b5051604080517f9be2faed000000000000000000000000000000000000000000000000000000008152306004820152600160a060020a03858116602483015291519190921691639be2faed916044808301926020929190829003018186803b15801561294c57600080fd5b505afa158015612960573d6000803e3d6000fd5b505050506040513d602081101561297657600080fd5b505115156129ce576040805160e560020a62461bcd02815260206004820152601860248201527f736368656d65206973206e6f7420726567697374657265640000000000000000604482015290519081900360640190fd5b81600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b158015612a0a57600080fd5b505afa158015612a1e573d6000803e3d6000fd5b505050506040513d6020811015612a3457600080fd5b5051604080517f1c4d5608000000000000000000000000000000000000000000000000000000008152306004820152600160a060020a03858116602483015291519190921691631c4d5608916044808301926020929190829003018186803b158015612a9f57600080fd5b505afa158015612ab3573d6000803e3d6000fd5b505050506040513d6020811015612ac957600080fd5b505192915050565b6000821515612ae257506000610c04565b828202828482811515612af157fe5b041461164557600080fd5b600082821115612b0b57600080fd5b50900390565b6101a0604051908101604052806000815260200160008152602001600081526020016000600160a060020a03168152602001600081526020016000600160a060020a03168152602001600081526020016000815260200160008152602001612b77612bd1565b905290565b604080518082019091526000808252602082015290565b8260048101928215612bc1579160200282015b82811115612bc1578251825591602001919060010190612ba6565b50612bcd929150612bf0565b5090565b6080604051908101604052806004906020820280388339509192915050565b612c0a91905b80821115612bcd5760008155600101612bf6565b9056fe706572696f644c656e67746820657175616c20302072657175697265206e756d6265724f66506572696f647320746f20626520316f6e6c7920566f74696e674d616368696e6500000000000000000000000000006e756d6265724f66506572696f6473202a20746f6b656e5265776172642077696c6c206f766572666c6f776e756d6265724f66506572696f6473202a2072657075746174696f6e4368616e67652077696c6c206f766572666c6f776e756d6265724f66506572696f6473202a206574685265776172642077696c6c206f766572666c6f776e756d6265724f66506572696f6473202a205f72657075746174696f6e4368616e67652077696c6c206f766572666c6f7773686f756c6420626520696e207468652072656465656d6564506572696f64732072616e67656e756d6265724f66506572696f6473202a207465787465726e616c546f6b656e5265776172642077696c6c206f766572666c6f77a165627a7a723058200eb8c8f2cb6ec53f6a032eecf43b0ccb0d69df3f3600ccaf877298559cd547d50029
Swarm Source
bzzr://0eb8c8f2cb6ec53f6a032eecf43b0ccb0d69df3f3600ccaf877298559cd547d5
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.