Address Contract Partially Verified
Address
0x970B9bB2C0444F5E81e9d0eFb84C8ccdcdcAf84d
Balance
0 ETH
Nonce
1
Code Size
8997 bytes
Creator
0xd9176e84...96C3 at tx 0xca7ceeb8...6cdc82
Indexed Transactions
0
Contract Bytecode
8997 bytes
0x6080604052600436106101a05763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146101a55780630804d35c1461022f578063095ea7b3146102525780630b26cf661461028a5780630d98dcb1146102ab5780631296830d146102ed57806318160ddd1461036057806323b872dd14610375578063313ce5671461039f57806339509351146103ca5780634000aea0146103ee57806340c10f191461041f57806342966c681461044357806346ea25521461045b5780634d8957571461048c57806369ffa08a1461054257806370a0823114610569578063715018a61461058a57806379cc67901461059f578063859ba28c146105c35780638da5cb5b146106045780638f32d59b1461061957806395d89b411461062e578063983b2d561461064357806398650275146106645780639a4b1d5c14610679578063a457c2d7146106a3578063a9059cbb146106c7578063aa271e1a146106eb578063cabc0a101461070c578063cd59658314610784578063dd62ed3e14610799578063f2fde38b146107c0575b600080fd5b3480156101b157600080fd5b506101ba6107e1565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101f45781810151838201526020016101dc565b50505050905090810190601f1680156102215780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023b57600080fd5b50610250600160a060020a0360043516610877565b005b34801561025e57600080fd5b50610276600160a060020a0360043516602435610912565b604080519115158252519081900360200190f35b34801561029657600080fd5b50610250600160a060020a0360043516610990565b3480156102b757600080fd5b506102db600160a060020a03600435811690602435166044356064356084356109fa565b60408051918252519081900360200190f35b3480156102f957600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261027694369492936024939284019190819084018382808284375094975050508335600160a060020a0316945050506020820135916040810135915060600135610ade565b34801561036c57600080fd5b506102db610ddf565b34801561038157600080fd5b50610276600160a060020a0360043581169060243516604435610de5565b3480156103ab57600080fd5b506103b4610e83565b6040805160ff9092168252519081900360200190f35b3480156103d657600080fd5b50610276600160a060020a0360043516602435610e8c565b3480156103fa57600080fd5b5061027660048035600160a060020a0316906024803591604435918201910135610f3c565b34801561042b57600080fd5b50610276600160a060020a036004351660243561104c565b34801561044f57600080fd5b50610250600435611075565b34801561046757600080fd5b50610470611082565b60408051600160a060020a039092168252519081900360200190f35b34801561049857600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261027694369492936024939284019190819084018382808284375050604080516020888301358a018035601f8101839004830284018301909452838352979a8935600160a060020a03169a8a8301359a919990985060609091019650919450908101925081908401838280828437509497505084359550505060209092013591506110919050565b34801561054e57600080fd5b50610250600160a060020a03600435811690602435166113b2565b34801561057557600080fd5b506102db600160a060020a0360043516611565565b34801561059657600080fd5b50610250611580565b3480156105ab57600080fd5b50610250600160a060020a0360043516602435611593565b3480156105cf57600080fd5b506105d86115a1565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b34801561061057600080fd5b506104706115ab565b34801561062557600080fd5b506102766115ba565b34801561063a57600080fd5b506101ba6115cb565b34801561064f57600080fd5b50610250600160a060020a036004351661162c565b34801561067057600080fd5b50610250611649565b34801561068557600080fd5b50610276600160a060020a0360043581169060243516604435611654565b3480156106af57600080fd5b50610276600160a060020a036004351660243561171a565b3480156106d357600080fd5b50610276600160a060020a0360043516602435611765565b3480156106f757600080fd5b50610276600160a060020a036004351661181b565b34801561071857600080fd5b50604080516020601f6064356004818101359283018490048402850184019095528184526102db94600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497505084359550505060209092013591506118349050565b34801561079057600080fd5b506104706119a4565b3480156107a557600080fd5b506102db600160a060020a03600435811690602435166119b3565b3480156107cc57600080fd5b50610250600160a060020a03600435166119de565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561086d5780601f106108425761010080835404028352916020019161086d565b820191906000526020600020905b81548152906001019060200180831161085057829003601f168201915b5050505050905090565b61087f6115ba565b151561088a57600080fd5b600160a060020a038116158015906108a657506108a6816119fa565b15156108b157600080fd5b600a8054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f2fa4d55ccac27bdda738b800a4659bc2763f3ed0ff623ff01d6e6b27638eb6739181900360200190a150565b6000600160a060020a038316151561092957600080fd5b336000818152600160209081526040808320600160a060020a03881680855290835292819020869055805186815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a350600192915050565b6109993361181b565b15156109a457600080fd5b600160a060020a038116158015906109c057506109c0816119fa565b15156109cb57600080fd5b6009805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b604080517f0d98dcb1000000000000000000000000000000000000000000000000000000006020808301919091526c01000000000000000000000000600160a060020a03808a16820260248501528816026038830152604c8201869052606c8201859052608c8083018590528351808403909101815260ac909201928390528151600093918291908401908083835b60208310610aa85780518252601f199092019160209182019101610a89565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209998505050505050505050565b600080808087600160a060020a03811615801590610b055750600160a060020a0381163014155b1515610b1057600080fd5b610b1d308a8a8a8a6109fa565b9350610b29848b611a02565b9250600160a060020a0383161515610b8b576040805160e560020a62461bcd02815260206004820152601e60248201527f496e76616c69642066726f6d2061646472657373207265636f76657265640000604482015290519081900360640190fd5b604080516c01000000000000000000000000600160a060020a03861602602080830191909152603480830188905283518084039091018152605490920192839052815191929182918401908083835b60208310610bf95780518252601f199092019160209182019101610bda565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912060008181526008909252929020549195505060ff16159150610cb59050576040805160e560020a62461bcd02815260206004820152602160248201527f5472616e73616374696f6e20686173682077617320616c72656164792075736560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b610cc233848b8b8b611ad7565b1515610ccd57600080fd5b600082815260086020908152604091829020805460ff1916600117905581518a815290810189905281513392600160a060020a038d811693908816927fec5a73fd1f178be20c1bca1b406cbf4b5c20d833b66e582fc122fb4baa0fc2a4929181900390910190a4610d3d896119fa565b8015610d645750604080516000815260208101909152610d629084908b908b90611b1b565b155b15610dcf57600954600160a060020a038a811691161415610d8457600080fd5b60408051600160a060020a0380861682528b1660208201528082018a905290517f11249f0fc79fc134a15a10d1da8291b79515bf987e036ced05b9ec119614070b9181900360600190a15b5060019998505050505050505050565b60025490565b600160a060020a0383166000908152600160209081526040808320338452909152812054821115610e1557600080fd5b600160a060020a0384166000908152600160209081526040808320338452909152902054610e49908363ffffffff611c7116565b600160a060020a0385166000908152600160209081526040808320338452909152902055610e78848484611c88565b5060015b9392505050565b60055460ff1690565b6000600160a060020a0383161515610ea357600080fd5b336000908152600160209081526040808320600160a060020a0387168452909152902054610ed7908363ffffffff611d7a16565b336000818152600160209081526040808320600160a060020a0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b600084600160a060020a03811615801590610f605750600160a060020a0381163014155b1515610f6b57600080fd5b610f758686611d8c565b1515610f8057600080fd5b85600160a060020a031633600160a060020a03167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16878787604051808481526020018060200182810382528484828181526020019250808284376040519201829003965090945050505050a3610ff5866119fa565b1561104057611035868686868080601f01602080910402602001604051908101604052809392919081815260200183838082843750611dae945050505050565b151561104057600080fd5b50600195945050505050565b60006110573361181b565b151561106257600080fd5b61106c8383611f03565b50600192915050565b61107f3382611fad565b50565b600a54600160a060020a031681565b600080808088600160a060020a038116158015906110b85750600160a060020a0381163014155b15156110c357600080fd5b6110d1308b8b8b8b8b611834565b93506110dd848c611a02565b9250600160a060020a038316151561113f576040805160e560020a62461bcd02815260206004820152601e60248201527f496e76616c69642066726f6d2061646472657373207265636f76657265640000604482015290519081900360640190fd5b604080516c01000000000000000000000000600160a060020a03861602602080830191909152603480830188905283518084039091018152605490920192839052815191929182918401908083835b602083106111ad5780518252601f19909201916020918201910161118e565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912060008181526008909252929020549195505060ff161591506112699050576040805160e560020a62461bcd02815260206004820152602160248201527f5472616e73616374696f6e20686173682077617320616c72656164792075736560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b61127633848c8c8b611ad7565b151561128157600080fd5b600160086000846000191660001916815260200190815260200160002060006101000a81548160ff02191690831515021790555033600160a060020a03168a600160a060020a031684600160a060020a03167f3f67b8b86a1e670c44e3cbe2858309134a8aaad71baff0170d7b8fb522c8fd388c8c8c6040518084815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611340578181015183820152602001611328565b50505050905090810190601f16801561136d5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a46113858a6119fa565b156113a157611396838b8b8b611b1b565b15156113a157600080fd5b5060019a9950505050505050505050565b6000806113bd6115ba565b15156113c857600080fd5b600160a060020a03831615156113dd57600080fd5b600160a060020a038416151561142957604051600160a060020a03841690303180156108fc02916000818181858888f19350505050158015611423573d6000803e3d6000fd5b5061155f565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051859350600160a060020a038416916370a082319160248083019260209291908290030181600087803b15801561148d57600080fd5b505af11580156114a1573d6000803e3d6000fd5b505050506040513d60208110156114b757600080fd5b5051604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0386811660048301526024820184905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b15801561152857600080fd5b505af115801561153c573d6000803e3d6000fd5b505050506040513d602081101561155257600080fd5b5051151561155f57600080fd5b50505050565b600160a060020a031660009081526020819052604090205490565b6115886115ba565b15156101a057600080fd5b61159d828261207b565b5050565b6003600080909192565b600754600160a060020a031690565b600754600160a060020a0316331490565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561086d5780601f106108425761010080835404028352916020019161086d565b6116353361181b565b151561164057600080fd5b61107f8161210d565b61165233612155565b565b600a54600090600160a060020a03161561171257600a54604080517f9a4b1d5c000000000000000000000000000000000000000000000000000000008152600160a060020a03878116600483015286811660248301526044820186905291519190921691639a4b1d5c9160648083019260209291908290030181600087803b1580156116df57600080fd5b505af11580156116f3573d6000803e3d6000fd5b505050506040513d602081101561170957600080fd5b50519050610e7c565b506001610e7c565b6000600160a060020a038316151561173157600080fd5b336000908152600160209081526040808320600160a060020a0387168452909152902054610ed7908363ffffffff611c7116565b60006117718383611d8c565b151561177c57600080fd5b611785836119fa565b80156117aa57506040805160008152602081019091526117a89084908490611dae565b155b1561106c57600954600160a060020a03848116911614156117ca57600080fd5b60408051338152600160a060020a038516602082015280820184905290517f11249f0fc79fc134a15a10d1da8291b79515bf987e036ced05b9ec119614070b9181900360600190a150600192915050565b600061182e60068363ffffffff61219d16565b92915050565b600063cabc0a107c0100000000000000000000000000000000000000000000000000000000028787878787876040516020018088600160e060020a031916600160e060020a031916815260040187600160a060020a0316600160a060020a03166c0100000000000000000000000002815260140186600160a060020a0316600160a060020a03166c0100000000000000000000000002815260140185815260200184805190602001908083835b602083106119005780518252601f1990920191602091820191016118e1565b51815160209384036101000a60001901801990921691161790529201948552508381019290925250604080518084038301815292810190819052825192975095508594508601925090508083835b6020831061196d5780518252601f19909201916020918201910161194e565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209a9950505050505050505050565b600954600160a060020a031681565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b6119e66115ba565b15156119f157600080fd5b61107f816121d4565b6000903b1190565b60008060008084516041141515611a1c5760009350611ace565b50505060208201516040830151606084015160001a601b60ff82161015611a4157601b015b8060ff16601b14158015611a5957508060ff16601c14155b15611a675760009350611ace565b60408051600080825260208083018085528a905260ff8516838501526060830187905260808301869052925160019360a0808501949193601f19840193928390039091019190865af1158015611ac1573d6000803e3d6000fd5b5050506020604051035193505b50505092915050565b6000611ae4858585611654565b1515611aef57600080fd5b611afa858784611654565b1515611b0557600080fd5b611b10858585611c88565b611040858784611c88565b600083600160a060020a03168584846040516024018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611b88578181015183820152602001611b70565b50505050905090810190601f168015611bb55780820380516001836020036101000a031916815260200191505b5060408051601f19818403018152918152602082018051600160e060020a03167fa4c0ed36000000000000000000000000000000000000000000000000000000001781529051825192975095508594509250905080838360005b83811015611c27578181015183820152602001611c0f565b50505050905090810190601f168015611c545780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1979650505050505050565b60008083831115611c8157600080fd5b5050900390565b600160a060020a038316600090815260208190526040902054811115611cad57600080fd5b600160a060020a0382161515611cc257600080fd5b600160a060020a038316600090815260208190526040902054611ceb908263ffffffff611c7116565b600160a060020a038085166000908152602081905260408082209390935590841681522054611d20908263ffffffff611d7a16565b600160a060020a038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600082820183811015610e7c57600080fd5b6000611d99338484611654565b1515611da457600080fd5b610e7c8383612252565b600083600160a060020a03163384846040516024018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611e1b578181015183820152602001611e03565b50505050905090810190601f168015611e485780820380516001836020036101000a031916815260200191505b5060408051601f19818403018152918152602082018051600160e060020a03167fa4c0ed36000000000000000000000000000000000000000000000000000000001781529051825192975095508594509250905080838360005b83811015611eba578181015183820152602001611ea2565b50505050905090810190601f168015611ee75780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af19695505050505050565b600160a060020a0382161515611f1857600080fd5b600254611f2b908263ffffffff611d7a16565b600255600160a060020a038216600090815260208190526040902054611f57908263ffffffff611d7a16565b600160a060020a0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600160a060020a0382161515611fc257600080fd5b600160a060020a038216600090815260208190526040902054811115611fe757600080fd5b600254611ffa908263ffffffff611c7116565b600255600160a060020a038216600090815260208190526040902054612026908263ffffffff611c7116565b600160a060020a038316600081815260208181526040808320949094558351858152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35050565b600160a060020a03821660009081526001602090815260408083203384529091529020548111156120ab57600080fd5b600160a060020a03821660009081526001602090815260408083203384529091529020546120df908263ffffffff611c7116565b600160a060020a038316600090815260016020908152604080832033845290915290205561159d8282611fad565b61211e60068263ffffffff61225f16565b604051600160a060020a038216907f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f690600090a250565b61216660068263ffffffff6122ad16565b604051600160a060020a038216907fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669290600090a250565b6000600160a060020a03821615156121b457600080fd5b50600160a060020a03166000908152602091909152604090205460ff1690565b600160a060020a03811615156121e957600080fd5b600754604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36007805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600061106c338484611c88565b600160a060020a038116151561227457600080fd5b61227e828261219d565b1561228857600080fd5b600160a060020a0316600090815260209190915260409020805460ff19166001179055565b600160a060020a03811615156122c257600080fd5b6122cc828261219d565b15156122d757600080fd5b600160a060020a0316600090815260209190915260409020805460ff191690555600a165627a7a7230582007e69935477055e354a328174b3e4e38f453f1268f28558864ab8f1297040e670029
Verified Source Code Partial Match
Compiler: v0.4.24+commit.e67f0147
EVM: byzantium
Optimization: Yes (200 runs)
ERC677BridgeToken.sol 1175 lines
// File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
pragma solidity ^0.4.24;
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender)
external view returns (uint256);
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);
event Transfer(
address indexed from,
address indexed to,
uint256 value
);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
// File: openzeppelin-solidity/contracts/math/SafeMath.sol
pragma solidity ^0.4.24;
/**
* @title SafeMath
* @dev Math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, 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 numbers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0); // Solidity only automatically asserts when dividing by 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 numbers, 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 numbers, 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 numbers 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.4.24;
/**
* @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
*/
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
* @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)
{
require(value <= _allowed[from][msg.sender]);
_allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
_transfer(from, to, value);
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
* @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
* @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(value <= _balances[from]);
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 != 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 != 0);
require(value <= _balances[account]);
_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.
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burnFrom(address account, uint256 value) internal {
require(value <= _allowed[account][msg.sender]);
// Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
// this function needs to emit an event with the updated approval.
_allowed[account][msg.sender] = _allowed[account][msg.sender].sub(
value);
_burn(account, value);
}
}
// File: openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol
pragma solidity ^0.4.24;
/**
* @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: openzeppelin-solidity/contracts/access/Roles.sol
pragma solidity ^0.4.24;
/**
* @title Roles
* @dev Library for managing addresses assigned to a Role.
*/
library Roles {
struct Role {
mapping (address => bool) bearer;
}
/**
* @dev give an account access to this role
*/
function add(Role storage role, address account) internal {
require(account != address(0));
require(!has(role, account));
role.bearer[account] = true;
}
/**
* @dev remove an account's access to this role
*/
function remove(Role storage role, address account) internal {
require(account != address(0));
require(has(role, account));
role.bearer[account] = false;
}
/**
* @dev check if an account has this role
* @return bool
*/
function has(Role storage role, address account)
internal
view
returns (bool)
{
require(account != address(0));
return role.bearer[account];
}
}
// File: openzeppelin-solidity/contracts/access/roles/MinterRole.sol
pragma solidity ^0.4.24;
contract MinterRole {
using Roles for Roles.Role;
event MinterAdded(address indexed account);
event MinterRemoved(address indexed account);
Roles.Role private minters;
constructor() internal {
_addMinter(msg.sender);
}
modifier onlyMinter() {
require(isMinter(msg.sender));
_;
}
function isMinter(address account) public view returns (bool) {
return minters.has(account);
}
function addMinter(address account) public onlyMinter {
_addMinter(account);
}
function renounceMinter() public {
_removeMinter(msg.sender);
}
function _addMinter(address account) internal {
minters.add(account);
emit MinterAdded(account);
}
function _removeMinter(address account) internal {
minters.remove(account);
emit MinterRemoved(account);
}
}
// File: openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol
pragma solidity ^0.4.24;
/**
* @title ERC20Mintable
* @dev ERC20 minting logic
*/
contract ERC20Mintable is ERC20, MinterRole {
/**
* @dev Function to mint tokens
* @param to The address that will receive the minted tokens.
* @param value The amount of tokens to mint.
* @return A boolean that indicates if the operation was successful.
*/
function mint(
address to,
uint256 value
)
public
onlyMinter
returns (bool)
{
_mint(to, value);
return true;
}
}
// File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol
pragma solidity ^0.4.24;
/**
* @title ERC20Detailed token
* @dev The decimals are only for visualization purposes.
* All the operations are done using the smallest and indivisible token unit,
* just as on Ethereum all the operations are done in wei.
*/
contract ERC20Detailed is IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
constructor(string name, string symbol, uint8 decimals) public {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
/**
* @return the name of the token.
*/
function name() public view returns(string) {
return _name;
}
/**
* @return the symbol of the token.
*/
function symbol() public view returns(string) {
return _symbol;
}
/**
* @return the number of decimals of the token.
*/
function decimals() public view returns(uint8) {
return _decimals;
}
}
// File: openzeppelin-solidity/contracts/ownership/Ownable.sol
pragma solidity ^0.4.24;
/**
* @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: contracts/ERC677.sol
pragma solidity 0.4.24;
contract ERC677 is ERC20 {
event Transfer(address indexed from, address indexed to, uint value, bytes data);
function transferAndCall(address, uint, bytes) external returns (bool);
}
// File: contracts/IBurnableMintableERC677Token.sol
pragma solidity 0.4.24;
contract IBurnableMintableERC677Token is ERC677 {
function mint(address, uint256) public returns (bool);
function burn(uint256 _value) public;
function claimTokens(address _token, address _to) public;
}
// File: contracts/ERC865.sol
pragma solidity 0.4.24;
contract ERC865 is ERC20 {
mapping(bytes32 => bool) hashedTxs;
event TransferPreSigned(address indexed from, address indexed to, address indexed delegate, uint256 amount, uint256 fee);
event TransferAndCallPreSigned(address indexed from, address indexed to, address indexed delegate, uint256 amount, bytes data, uint256 fee);
/**
* @param _signature bytes The signature, issued by the owner.
* @param _to address The address which you want to transfer to.
* @param _value uint256 The amount of tokens to be transferred.
* @param _fee uint256 The amount of tokens paid to msg.sender, by the owner.
* @param _timestamp uint256 Timestamp of transaction, for uniqueness.
*/
function transferPreSigned(bytes _signature, address _to, uint256 _value, uint256 _fee, uint256 _timestamp) public returns (bool);
/**
* @param _signature bytes The signature, issued by the owner.
* @param _to address The address which you want to transfer to.
* @param _value uint256 The amount of tokens to be transferred.
* @param _data bytes The data which enables the pass additional params.
* @param _fee uint256 The amount of tokens paid to msg.sender, by the owner.
* @param _timestamp uint256 Timestamp of transaction, for uniqueness.
*/
function transferAndCallPreSigned(bytes _signature, address _to, uint256 _value, bytes _data, uint256 _fee, uint256 _timestamp) public returns (bool);
/**
* @param _token address The address of the token.
* @param _to address The address which you want to transfer to.
* @param _value uint256 The amount of tokens to be transferred.
* @param _fee uint256 The amount of tokens paid to msg.sender, by the owner.
* @param _timestamp uint256 Timestamp of transaction, for uniqueness.
*/
function getTransferPreSignedHash(address _token, address _to, uint256 _value, uint256 _fee, uint256 _timestamp) public pure returns (bytes32);
/**
* @param _token address The address of the token.
* @param _to address The address which you want to transfer to.
* @param _value uint256 The amount of tokens to be transferred.
* @param _data bytes The data which enables the pass additional params
* @param _fee uint256 The amount of tokens paid to msg.sender, by the owner.
* @param _timestamp uint256 Timestamp of transaction, for uniqueness.
*/
function getTransferAndCallPreSignedHash(address _token, address _to, uint256 _value, bytes _data, uint256 _fee, uint256 _timestamp) public pure returns (bytes32);
}
// File: contracts/ERC677Receiver.sol
pragma solidity 0.4.24;
contract ERC677Receiver {
function onTokenTransfer(address _from, uint _value, bytes _data) external returns(bool);
}
// File: contracts/IBridgeValidators.sol
pragma solidity 0.4.24;
interface IBridgeValidators {
function initialize(uint256 _requiredSignatures, address[] _initialValidators, address _owner) public returns(bool);
function isValidator(address _validator) public view returns(bool);
function requiredSignatures() public view returns(uint256);
function owner() public view returns(address);
}
// File: contracts/IForeignBridgeValidators.sol
pragma solidity 0.4.24;
interface IForeignBridgeValidators {
function isValidator(address _validator) public view returns(bool);
function requiredSignatures() public view returns(uint256);
function setValidators(address[] _validators) public returns(bool);
}
// File: contracts/libraries/Message.sol
pragma solidity 0.4.24;
library Message {
function addressArrayContains(address[] array, address value) internal pure returns (bool) {
for (uint256 i = 0; i < array.length; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}
// layout of message :: bytes:
// offset 0: 32 bytes :: uint256 - message length
// offset 32: 20 bytes :: address - recipient address
// offset 52: 32 bytes :: uint256 - value
// offset 84: 32 bytes :: bytes32 - transaction hash
// offset 104: 20 bytes :: address - contract address to prevent double spending
// bytes 1 to 32 are 0 because message length is stored as little endian.
// mload always reads 32 bytes.
// so we can and have to start reading recipient at offset 20 instead of 32.
// if we were to read at 32 the address would contain part of value and be corrupted.
// when reading from offset 20 mload will read 12 zero bytes followed
// by the 20 recipient address bytes and correctly convert it into an address.
// this saves some storage/gas over the alternative solution
// which is padding address to 32 bytes and reading recipient at offset 32.
// for more details see discussion in:
// https://github.com/paritytech/parity-bridge/issues/61
function parseMessage(bytes message)
internal
pure
returns(address recipient, uint256 amount, bytes32 txHash, address contractAddress)
{
require(isMessageValid(message));
assembly {
recipient := and(mload(add(message, 20)), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
amount := mload(add(message, 52))
txHash := mload(add(message, 84))
contractAddress := mload(add(message, 104))
}
}
function parseNewSetMessage(bytes message)
internal
returns(address[] memory newSet, bytes32 txHash, address contractAddress)
{
uint256 msgLength;
uint256 position;
address newSetMember;
assembly {
msgLength := mload(message)
txHash := mload(add(message, 32))
contractAddress := mload(add(message, 52))
position := 72
}
uint256 newSetLength = (msgLength - position) / 20 + 1;
newSet = new address[](newSetLength);
uint256 i = 0;
while (position <= msgLength) {
assembly {
newSetMember := mload(add(message, position))
}
newSet[i] = newSetMember;
position += 20;
i++;
}
return (newSet, txHash, contractAddress);
}
function isMessageValid(bytes _msg) internal pure returns(bool) {
return _msg.length == requiredMessageLength();
}
function requiredMessageLength() internal pure returns(uint256) {
return 104;
}
function recoverAddressFromSignedMessage(bytes signature, bytes message, bool knownLength) internal pure returns (address) {
require(signature.length == 65);
bytes32 r;
bytes32 s;
bytes1 v;
// solium-disable-next-line security/no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := mload(add(signature, 0x60))
}
if (knownLength) {
return ecrecover(hashMessage(message), uint8(v), r, s);
} else {
return ecrecover(hashMessageOfUnknownLength(message), uint8(v), r, s);
}
}
function hashMessage(bytes message) internal pure returns (bytes32) {
bytes memory prefix = "\x19Ethereum Signed Message:\n";
// message is always 84 length
string memory msgLength = "104";
return keccak256(abi.encodePacked(prefix, msgLength, message));
}
function hashMessageOfUnknownLength(bytes message) internal pure returns (bytes32) {
bytes memory prefix = "\x19Ethereum Signed Message:\n";
uint256 lengthOffset;
uint256 length;
assembly {
// The first word of a string is its length
length := mload(message)
// The beginning of the base-10 message length in the prefix
lengthOffset := add(prefix, 57)
}
uint256 lengthLength = 0;
// The divisor to get the next left-most message length digit
uint256 divisor = 100000;
// Move one digit of the message length to the right at a time
while (divisor != 0) {
// The place value at the divisor
uint256 digit = length / divisor;
if (digit == 0) {
// Skip leading zeros
if (lengthLength == 0) {
divisor /= 10;
continue;
}
}
// Found a non-zero digit or non-leading zero digit
lengthLength++;
// Remove this digit from the message length's current value
length -= digit * divisor;
// Shift our base-10 divisor over
divisor /= 10;
// Convert the digit to its ASCII representation (man ascii)
digit += 0x30;
// Move to the next character and write the digit
lengthOffset++;
assembly {
mstore8(lengthOffset, digit)
}
}
// The null string requires exactly 1 zero (unskip 1 leading 0)
if (lengthLength == 0) {
lengthLength = 1 + 0x19 + 1;
} else {
lengthLength += 1 + 0x19;
}
// Truncate the tailing zeros from the prefix
assembly {
mstore(prefix, lengthLength)
}
return keccak256(prefix, message);
}
function hasEnoughValidSignatures(
bytes _message,
uint8[] _vs,
bytes32[] _rs,
bytes32[] _ss,
IBridgeValidators _validatorContract) internal view
{
uint256 requiredSignatures = _validatorContract.requiredSignatures();
require(_vs.length >= requiredSignatures);
bytes32 hash = hashMessage(_message);
address[] memory encounteredAddresses = new address[](requiredSignatures);
for (uint256 i = 0; i < requiredSignatures; i++) {
address recoveredAddress = ecrecover(hash, _vs[i], _rs[i], _ss[i]);
require(_validatorContract.isValidator(recoveredAddress));
if (addressArrayContains(encounteredAddresses, recoveredAddress)) {
revert();
}
encounteredAddresses[i] = recoveredAddress;
}
}
function hasEnoughValidSignaturesForeignBridgeValidator(
bytes _message,
uint8[] _vs,
bytes32[] _rs,
bytes32[] _ss,
IForeignBridgeValidators _validatorContract) internal view
{
uint256 requiredSignatures = _validatorContract.requiredSignatures();
require(_vs.length >= requiredSignatures);
bytes32 hash = hashMessage(_message);
address[] memory encounteredAddresses = new address[](requiredSignatures);
for (uint256 i = 0; i < requiredSignatures; i++) {
address recoveredAddress = ecrecover(hash, _vs[i], _rs[i], _ss[i]);
require(_validatorContract.isValidator(recoveredAddress));
if (addressArrayContains(encounteredAddresses, recoveredAddress)) {
revert();
}
encounteredAddresses[i] = recoveredAddress;
}
}
function hasEnoughValidNewSetSignaturesForeignBridgeValidator(
bytes _message,
uint8[] _vs,
bytes32[] _rs,
bytes32[] _ss,
IForeignBridgeValidators _validatorContract) internal view
{
uint256 requiredSignatures = _validatorContract.requiredSignatures();
require(_vs.length >= requiredSignatures);
bytes32 hash = hashMessageOfUnknownLength(_message);
address[] memory encounteredAddresses = new address[](requiredSignatures);
for (uint256 i = 0; i < requiredSignatures; i++) {
address recoveredAddress = ecrecover(hash, _vs[i], _rs[i], _ss[i]);
require(_validatorContract.isValidator(recoveredAddress));
if (addressArrayContains(encounteredAddresses, recoveredAddress)) {
revert();
}
encounteredAddresses[i] = recoveredAddress;
}
}
function recover(bytes32 hash, bytes sig) internal pure returns (address) {
bytes32 r;
bytes32 s;
uint8 v;
// Check the signature length
if (sig.length != 65) {
return (address(0));
}
// Divide the signature in r, s and v variables
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
// 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);
}
}
}
// File: contracts/ITransferManager.sol
pragma solidity ^0.4.24;
/**
* @title Interface to be implemented by all Transfer Manager modules
* @dev abstract contract
*/
contract ITransferManager {
function verifyTransfer(address _from, address _to, uint256 _amount) public view returns(bool);
}
// File: contracts/IRestrictedToken.sol
pragma solidity 0.4.24;
interface IRestrictedToken {
event TransferManagerSet(address transferManager);
function setTransferManager(address _transferManager) external;
function verifyTransfer(address _from, address _to, uint256 _value) external view;
}
// File: contracts/ERC677BridgeToken.sol
pragma solidity 0.4.24;
contract ERC677BridgeToken is
IBurnableMintableERC677Token,
IRestrictedToken,
ERC20Detailed,
ERC20Burnable,
ERC20Mintable,
Ownable,
ERC865 {
address public bridgeContract;
ITransferManager public transferManager;
event ContractFallbackCallFailed(address from, address to, uint value);
constructor(
string _name,
string _symbol,
uint8 _decimals)
public ERC20Detailed(_name, _symbol, _decimals) {}
function setBridgeContract(address _bridgeContract) onlyMinter public {
require(_bridgeContract != address(0) && isContract(_bridgeContract));
bridgeContract = _bridgeContract;
}
function setTransferManager(address _transferManager) onlyOwner public {
require(_transferManager != address(0) && isContract(_transferManager));
transferManager = ITransferManager(_transferManager);
emit TransferManagerSet(_transferManager);
}
modifier validRecipient(address _recipient) {
require(_recipient != address(0) && _recipient != address(this));
_;
}
function verifyTransfer(address _from, address _to, uint256 _value) public view returns (bool) {
if (transferManager != address(0)) {
return transferManager.verifyTransfer(_from, _to, _value);
} else {
return true;
}
}
function transferAndCall(address _to, uint _value, bytes _data)
external validRecipient(_to) returns (bool)
{
require(superTransfer(_to, _value));
emit Transfer(msg.sender, _to, _value, _data);
if (isContract(_to)) {
require(contractFallback(_to, _value, _data));
}
return true;
}
function getTokenInterfacesVersion() public pure returns(uint64 major, uint64 minor, uint64 patch) {
return (3, 0, 0);
}
function superTransfer(address _to, uint256 _value) internal returns(bool)
{
require(verifyTransfer(msg.sender, _to, _value));
return super.transfer(_to, _value);
}
/**
* @dev ERC20 transfer with a contract fallback.
* Contract fallback to bridge is a special, That's the transfer to other network
* @param _to The address to transfer to.
* @param _value The amount to be transferred.
*/
function transfer(address _to, uint256 _value) public returns (bool)
{
require(superTransfer(_to, _value));
if (isContract(_to) && !contractFallback(_to, _value, new bytes(0))) {
if (_to == bridgeContract) {
revert();
} else {
emit ContractFallbackCallFailed(msg.sender, _to, _value);
}
}
return true;
}
function contractFallback(address _to, uint _value, bytes _data)
private
returns(bool)
{
return _to.call(abi.encodeWithSignature("onTokenTransfer(address,uint256,bytes)", msg.sender, _value, _data));
}
function isContract(address _addr)
internal
view
returns (bool)
{
uint length;
assembly { length := extcodesize(_addr) }
return length > 0;
}
function renounceOwnership() public onlyOwner {
revert();
}
/**
* @dev Claims token or ether sent by mistake to the token contract
* @param _token The address to the token sent a null for ether.
* @param _to The address to to sent the tokens.
*/
function claimTokens(address _token, address _to) public onlyOwner {
require(_to != address(0));
if (_token == address(0)) {
_to.transfer(address(this).balance);
return;
}
ERC20Detailed token = ERC20Detailed(_token);
uint256 balance = token.balanceOf(address(this));
require(token.transfer(_to, balance));
}
function transferWithFee(address _sender, address _from, address _to, uint256 _value, uint256 _fee) internal returns(bool)
{
require(verifyTransfer(_from, _to, _value));
require(verifyTransfer(_from, _sender, _fee));
_transfer(_from, _to, _value);
_transfer(_from, _sender, _fee);
return true;
}
function contractFallbackFrom(address _from, address _to, uint _value, bytes _data) private returns(bool)
{
return _to.call(abi.encodeWithSignature("onTokenTransfer(address,uint256,bytes)", _from, _value, _data));
}
function transferPreSigned(bytes _signature, address _to, uint256 _value, uint256 _fee, uint256 _timestamp) validRecipient(_to) public returns (bool) {
bytes32 hashedParams = getTransferPreSignedHash(address(this), _to, _value, _fee, _timestamp);
address from = Message.recover(hashedParams, _signature);
require(from != address(0), "Invalid from address recovered");
bytes32 hashedTx = keccak256(abi.encodePacked(from, hashedParams));
require(hashedTxs[hashedTx] == false, "Transaction hash was already used");
require(transferWithFee(msg.sender, from, _to, _value, _fee));
hashedTxs[hashedTx] = true;
emit TransferPreSigned(from, _to, msg.sender, _value, _fee);
if (isContract(_to) && !contractFallbackFrom(from, _to, _value, new bytes(0))) {
if (_to == bridgeContract) {
revert();
} else {
emit ContractFallbackCallFailed(from, _to, _value);
}
}
return true;
}
function getTransferPreSignedHash(address _token, address _to, uint256 _value, uint256 _fee, uint256 _timestamp) public pure returns (bytes32) {
/* "0d98dcb1": getTransferPreSignedHash(address,address,uint256,uint256,uint256) */
return keccak256(abi.encodePacked(bytes4(0x0d98dcb1), _token, _to, _value, _fee, _timestamp));
}
function transferAndCallPreSigned(bytes _signature, address _to, uint256 _value, bytes _data, uint256 _fee, uint256 _timestamp) validRecipient(_to) public returns (bool) {
bytes32 hashedParams = getTransferAndCallPreSignedHash(address(this), _to, _value, _data, _fee, _timestamp);
address from = Message.recover(hashedParams, _signature);
require(from != address(0), "Invalid from address recovered");
bytes32 hashedTx = keccak256(abi.encodePacked(from, hashedParams));
require(hashedTxs[hashedTx] == false, "Transaction hash was already used");
require(transferWithFee(msg.sender, from, _to, _value, _fee));
hashedTxs[hashedTx] = true;
emit TransferAndCallPreSigned(from, _to, msg.sender, _value, _data, _fee);
if (isContract(_to)) {
require(contractFallbackFrom(from, _to, _value, _data));
}
return true;
}
function getTransferAndCallPreSignedHash(address _token, address _to, uint256 _value, bytes _data, uint256 _fee, uint256 _timestamp) public pure returns (bytes32) {
/* "cabc0a10": getTransferPreSignedHash(address,address,uint256,uint256,uint256) */
return keccak256(abi.encodePacked(bytes4(0xcabc0a10), _token, _to, _value, _data, _fee, _timestamp));
}
}
Read Contract
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
bridgeContract 0xcd596583 → address
decimals 0x313ce567 → uint8
getTokenInterfacesVersion 0x859ba28c → uint64, uint64, uint64
getTransferAndCallPreSignedHash 0xcabc0a10 → bytes32
getTransferPreSignedHash 0x0d98dcb1 → bytes32
isMinter 0xaa271e1a → bool
isOwner 0x8f32d59b → bool
name 0x06fdde03 → string
owner 0x8da5cb5b → address
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
transferManager 0x46ea2552 → address
verifyTransfer 0x9a4b1d5c → bool
Write Contract 18 functions
These functions modify contract state and require a wallet transaction to execute.
addMinter 0x983b2d56
address account
approve 0x095ea7b3
address spender
uint256 value
returns: bool
burn 0x42966c68
uint256 value
burnFrom 0x79cc6790
address from
uint256 value
claimTokens 0x69ffa08a
address _token
address _to
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
mint 0x40c10f19
address to
uint256 value
returns: bool
renounceMinter 0x98650275
No parameters
renounceOwnership 0x715018a6
No parameters
setBridgeContract 0x0b26cf66
address _bridgeContract
setTransferManager 0x0804d35c
address _transferManager
transfer 0xa9059cbb
address _to
uint256 _value
returns: bool
transferAndCall 0x4000aea0
address _to
uint256 _value
bytes _data
returns: bool
transferAndCallPreSigned 0x4d895757
bytes _signature
address _to
uint256 _value
bytes _data
uint256 _fee
uint256 _timestamp
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool
transferOwnership 0xf2fde38b
address newOwner
transferPreSigned 0x1296830d
bytes _signature
address _to
uint256 _value
uint256 _fee
uint256 _timestamp
returns: bool
Recent Transactions
No transactions found for this address