编译器
0.6.12+commit.27d51765
文件 1 的 5:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 5:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./SafeMath.sol";
import "./Address.sol";
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 3 的 5:Peggy.sol
pragma solidity ^0.6.0;
import "./SafeMath.sol";
import "./IERC20.sol";
import "./SafeERC20.sol";
contract Peggy {
using SafeMath for uint256;
using SafeERC20 for IERC20;
bytes32 public state_lastValsetCheckpoint;
mapping(address => uint256) public state_lastBatchNonces;
uint256 public state_lastValsetNonce = 0;
uint256 public state_lastEventNonce = 0;
bytes32 public state_peggyId;
uint256 public state_powerThreshold;
bool public halted = false;
bool public depositsStopped = false;
address public guardian;
event TransactionBatchExecutedEvent(
uint256 indexed _batchNonce,
address indexed _token,
address indexed _sender,
uint256 _eventNonce
);
event SendToHubEvent(
address indexed _tokenContract,
address indexed _sender,
bytes32 indexed _destination,
uint256 _amount,
uint256 _eventNonce
);
event SendToMinterEvent(
address indexed _tokenContract,
address indexed _sender,
bytes32 indexed _destination,
uint256 _amount,
uint256 _eventNonce
);
event ValsetUpdatedEvent(
uint256 indexed _newValsetNonce,
address[] _validators,
uint256[] _powers
);
function lastBatchNonce(address _erc20Address) public view returns (uint256) {
return state_lastBatchNonces[_erc20Address];
}
function verifySig(
address _signer,
bytes32 _theHash,
uint8 _v,
bytes32 _r,
bytes32 _s
) private pure returns (bool) {
bytes32 messageDigest = keccak256(
abi.encodePacked("\x19Ethereum Signed Message:\n32", _theHash)
);
return _signer == ecrecover(messageDigest, _v, _r, _s);
}
function makeCheckpoint(
address[] memory _validators,
uint256[] memory _powers,
uint256 _valsetNonce,
bytes32 _peggyId
) private pure returns (bytes32) {
bytes32 methodName = 0x636865636b706f696e7400000000000000000000000000000000000000000000;
bytes32 checkpoint = keccak256(
abi.encode(_peggyId, methodName, _valsetNonce, _validators, _powers)
);
return checkpoint;
}
function checkValidatorSignatures(
address[] memory _currentValidators,
uint256[] memory _currentPowers,
uint8[] memory _v,
bytes32[] memory _r,
bytes32[] memory _s,
bytes32 _theHash,
uint256 _powerThreshold
) private pure {
uint256 cumulativePower = 0;
for (uint256 i = 0; i < _currentValidators.length; i++) {
if (_v[i] != 0) {
require(
verifySig(_currentValidators[i], _theHash, _v[i], _r[i], _s[i]),
"Validator signature does not match."
);
cumulativePower = cumulativePower + _currentPowers[i];
if (cumulativePower > _powerThreshold) {
break;
}
}
}
require(
cumulativePower > _powerThreshold,
"Submitted validator set signatures do not have enough power."
);
}
function updateValset(
address[] memory _newValidators,
uint256[] memory _newPowers,
uint256 _newValsetNonce,
address[] memory _currentValidators,
uint256[] memory _currentPowers,
uint256 _currentValsetNonce,
uint8[] memory _v,
bytes32[] memory _r,
bytes32[] memory _s
) public {
require(!halted, "contract halted");
require(
_newValsetNonce > _currentValsetNonce,
"New valset nonce must be greater than the current nonce"
);
require(_newValidators.length == _newPowers.length, "Malformed new validator set");
require(
_currentValidators.length == _currentPowers.length &&
_currentValidators.length == _v.length &&
_currentValidators.length == _r.length &&
_currentValidators.length == _s.length,
"Malformed current validator set"
);
require(
makeCheckpoint(
_currentValidators,
_currentPowers,
_currentValsetNonce,
state_peggyId
) == state_lastValsetCheckpoint,
"Supplied current validators and powers do not match checkpoint."
);
bytes32 newCheckpoint = makeCheckpoint(
_newValidators,
_newPowers,
_newValsetNonce,
state_peggyId
);
checkValidatorSignatures(
_currentValidators,
_currentPowers,
_v,
_r,
_s,
newCheckpoint,
state_powerThreshold
);
state_lastValsetCheckpoint = newCheckpoint;
state_lastValsetNonce = _newValsetNonce;
emit ValsetUpdatedEvent(_newValsetNonce, _newValidators, _newPowers);
}
function submitBatch(
address[] memory _currentValidators,
uint256[] memory _currentPowers,
uint256 _currentValsetNonce,
uint8[] memory _v,
bytes32[] memory _r,
bytes32[] memory _s,
uint256[] memory _amounts,
address[] memory _destinations,
uint256 _batchNonce,
address _tokenContract
) public {
{
require(!halted, "contract halted");
require(
state_lastBatchNonces[_tokenContract] < _batchNonce,
"New batch nonce must be greater than the current nonce"
);
require(
_currentValidators.length == _currentPowers.length &&
_currentValidators.length == _v.length &&
_currentValidators.length == _r.length &&
_currentValidators.length == _s.length,
"Malformed current validator set"
);
require(
makeCheckpoint(
_currentValidators,
_currentPowers,
_currentValsetNonce,
state_peggyId
) == state_lastValsetCheckpoint,
"Supplied current validators and powers do not match checkpoint."
);
require(
_amounts.length == _destinations.length,
"Malformed batch of transactions"
);
checkValidatorSignatures(
_currentValidators,
_currentPowers,
_v,
_r,
_s,
keccak256(
abi.encode(
state_peggyId,
0x7472616e73616374696f6e426174636800000000000000000000000000000000,
_amounts,
_destinations,
_batchNonce,
_tokenContract
)
),
state_powerThreshold
);
state_lastBatchNonces[_tokenContract] = _batchNonce;
{
for (uint256 i = 0; i < _amounts.length; i++) {
IERC20(_tokenContract).safeTransfer(_destinations[i], _amounts[i]);
}
}
}
{
state_lastEventNonce = state_lastEventNonce.add(1);
emit TransactionBatchExecutedEvent(_batchNonce, _tokenContract, msg.sender, state_lastEventNonce);
}
}
function sendToHub(
address _tokenContract,
bytes32 _destination,
uint256 _amount
) public {
require(!halted, "contract halted");
require(!depositsStopped, "deposits stopped");
IERC20(_tokenContract).safeTransferFrom(msg.sender, address(this), _amount);
state_lastEventNonce = state_lastEventNonce.add(1);
emit SendToHubEvent(
_tokenContract,
msg.sender,
_destination,
_amount,
state_lastEventNonce
);
}
function sendToMinter(
address _tokenContract,
bytes32 _destination,
uint256 _amount
) public {
IERC20(_tokenContract).safeTransferFrom(msg.sender, address(this), _amount);
state_lastEventNonce = state_lastEventNonce.add(1);
emit SendToMinterEvent(
_tokenContract,
msg.sender,
_destination,
_amount,
state_lastEventNonce
);
}
function toggleHalt() public {
require(msg.sender == guardian, "permission denied");
halted = !halted;
}
function toggleDeposits() public {
require(msg.sender == guardian, "permission denied");
depositsStopped = !depositsStopped;
}
function changeGuardian(address _guardian) public {
require(msg.sender == guardian, "permission denied");
guardian = _guardian;
}
function panicHalt(address[] memory _tokenContracts, address _safeAddress) public {
require(msg.sender == guardian, "permission denied");
halted = true;
depositsStopped = true;
for (uint256 i = 0; i < _tokenContracts.length; i++) {
IERC20 token = IERC20(_tokenContracts[i]);
token.safeTransfer(_safeAddress, token.balanceOf(address(this)));
}
}
constructor(
bytes32 _peggyId,
uint256 _powerThreshold,
address[] memory _validators,
uint256[] memory _powers,
address _guardian
) public {
require(_validators.length == _powers.length, "Malformed current validator set");
uint256 cumulativePower = 0;
for (uint256 i = 0; i < _powers.length; i++) {
cumulativePower = cumulativePower + _powers[i];
if (cumulativePower > _powerThreshold) {
break;
}
}
require(
cumulativePower > _powerThreshold,
"Submitted validator set signatures do not have enough power."
);
bytes32 newCheckpoint = makeCheckpoint(_validators, _powers, 0, _peggyId);
state_peggyId = _peggyId;
state_powerThreshold = _powerThreshold;
state_lastValsetCheckpoint = newCheckpoint;
guardian = _guardian;
emit ValsetUpdatedEvent(0, _validators, _powers);
}
}
文件 4 的 5:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./SafeMath.sol";
import "./Address.sol";
import "./IERC20.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 5 的 5:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
{
"compilationTarget": {
"Peggy.sol": "Peggy"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"bytes32","name":"_peggyId","type":"bytes32"},{"internalType":"uint256","name":"_powerThreshold","type":"uint256"},{"internalType":"address[]","name":"_validators","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"},{"internalType":"address","name":"_guardian","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_tokenContract","type":"address"},{"indexed":true,"internalType":"address","name":"_sender","type":"address"},{"indexed":true,"internalType":"bytes32","name":"_destination","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"SendToHubEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_tokenContract","type":"address"},{"indexed":true,"internalType":"address","name":"_sender","type":"address"},{"indexed":true,"internalType":"bytes32","name":"_destination","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"SendToMinterEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_batchNonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"address","name":"_sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"TransactionBatchExecutedEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_newValsetNonce","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"_validators","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"ValsetUpdatedEvent","type":"event"},{"inputs":[{"internalType":"address","name":"_guardian","type":"address"}],"name":"changeGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositsStopped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"halted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_erc20Address","type":"address"}],"name":"lastBatchNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokenContracts","type":"address[]"},{"internalType":"address","name":"_safeAddress","type":"address"}],"name":"panicHalt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenContract","type":"address"},{"internalType":"bytes32","name":"_destination","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sendToHub","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenContract","type":"address"},{"internalType":"bytes32","name":"_destination","type":"bytes32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sendToMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"state_lastBatchNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_lastEventNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_lastValsetCheckpoint","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_lastValsetNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_peggyId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_powerThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_currentValidators","type":"address[]"},{"internalType":"uint256[]","name":"_currentPowers","type":"uint256[]"},{"internalType":"uint256","name":"_currentValsetNonce","type":"uint256"},{"internalType":"uint8[]","name":"_v","type":"uint8[]"},{"internalType":"bytes32[]","name":"_r","type":"bytes32[]"},{"internalType":"bytes32[]","name":"_s","type":"bytes32[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address[]","name":"_destinations","type":"address[]"},{"internalType":"uint256","name":"_batchNonce","type":"uint256"},{"internalType":"address","name":"_tokenContract","type":"address"}],"name":"submitBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleHalt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_newValidators","type":"address[]"},{"internalType":"uint256[]","name":"_newPowers","type":"uint256[]"},{"internalType":"uint256","name":"_newValsetNonce","type":"uint256"},{"internalType":"address[]","name":"_currentValidators","type":"address[]"},{"internalType":"uint256[]","name":"_currentPowers","type":"uint256[]"},{"internalType":"uint256","name":"_currentValsetNonce","type":"uint256"},{"internalType":"uint8[]","name":"_v","type":"uint8[]"},{"internalType":"bytes32[]","name":"_r","type":"bytes32[]"},{"internalType":"bytes32[]","name":"_s","type":"bytes32[]"}],"name":"updateValset","outputs":[],"stateMutability":"nonpayable","type":"function"}]