编译器
0.8.14+commit.80d49f37
文件 1 的 6:Context.sol
pragma solidity 0.8.14;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 2 的 6:ERC20.sol
pragma solidity 0.8.14;
import "IERC20.sol";
import "IERC20Metadata.sol";
import "Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
文件 3 的 6:Escrow_v1.0.0.sol
pragma solidity 0.8.14;
import "Token.sol";
contract Escrow_v100 {
address public immutable buyer;
address public immutable seller;
address private immutable agent;
uint256 public immutable contractPrice;
uint256 public immutable buyerProtectionTime;
Token public token;
enum ContractStateChoices {
DEPLOYED,
FULFILLED,
EXECUTED,
DISPUTED,
AGENT_INVITED,
DISPUTE_FINISHED
}
ContractStateChoices public ContractState;
uint256 public executionTimestamp;
uint256 public immutable version;
constructor(
address _buyer,
address _seller,
address _agent,
address _token,
uint256 _contractPrice,
uint256 _buyerProtectionTime
) {
require(_buyer != _seller || _agent != _seller || _agent != _buyer, 'e001');
require(msg.sender == _buyer, 'e003');
require(_contractPrice > 0, 'e006');
require(_buyerProtectionTime >= 60*60*24, 'e007');
require(isContract(_token), 'e019');
contractPrice = _contractPrice;
buyer = _buyer;
seller = _seller;
agent = _agent;
token = Token(_token);
ContractState = ContractStateChoices.DEPLOYED;
buyerProtectionTime = _buyerProtectionTime;
version = 100;
}
function confirmFulfillment() external {
require(msg.sender == seller, 'e004');
require(ContractState == ContractStateChoices.DEPLOYED, 'e013');
require(getBalanceOfContract() >= contractPrice, 'e002');
ContractState = ContractStateChoices.FULFILLED;
executionTimestamp = getCurrentTimestamp();
}
function release() external {
require(msg.sender == buyer || msg.sender == seller, 'e012');
require(
ContractState == ContractStateChoices.DEPLOYED ||
ContractState == ContractStateChoices.FULFILLED ||
ContractState == ContractStateChoices.DISPUTED,
'e017');
require(getBalanceOfContract() >= contractPrice, 'e002');
if (msg.sender == seller) {
require(getCurrentTimestamp() > executionTimestamp + buyerProtectionTime, 'e009');
require(ContractState == ContractStateChoices.FULFILLED, 'e014');
}
token.transfer(seller, contractPrice);
ContractState = ContractStateChoices.EXECUTED;
}
function openDispute() external {
require(msg.sender == buyer, 'e003');
require(
ContractState == ContractStateChoices.DEPLOYED ||
ContractState == ContractStateChoices.FULFILLED,
'e018');
require(getBalanceOfContract() >= contractPrice, 'e002');
ContractState = ContractStateChoices.DISPUTED;
}
function inviteAgent() external {
require(msg.sender == buyer || msg.sender == seller, 'e012');
require(ContractState == ContractStateChoices.DISPUTED, 'e015');
ContractState = ContractStateChoices.AGENT_INVITED;
}
function sendMoney(uint256 _agentPercent, uint256 _buyerPercent, uint256 _sellerPercent) external {
require(msg.sender == agent, 'e005');
require(ContractState == ContractStateChoices.AGENT_INVITED, 'e016');
require(_agentPercent >= 1 && _agentPercent <= 3, 'e010');
require(_agentPercent + _buyerPercent + _sellerPercent == 100, 'e011');
uint256 agentFee = _agentPercent * (getBalanceOfContract() - (getBalanceOfContract() - contractPrice)) / 100;
uint256 buyerPart = _buyerPercent * (getBalanceOfContract() - (getBalanceOfContract() - contractPrice)) / 100;
uint256 sellerPart = _sellerPercent * (getBalanceOfContract() - (getBalanceOfContract() - contractPrice)) / 100;
token.transfer(agent, agentFee);
token.transfer(buyer, buyerPart);
token.transfer(seller, sellerPart);
ContractState = ContractStateChoices.DISPUTE_FINISHED;
}
function returnMoney(address _token) external {
require(msg.sender == buyer, 'e003');
if (_token == address(token)) {
if (token.balanceOf(address(this)) > contractPrice) {
if (ContractState == ContractStateChoices.EXECUTED || ContractState == ContractStateChoices.DISPUTE_FINISHED) {
token.transfer(msg.sender, token.balanceOf(address(this)));
} else {
token.transfer(msg.sender, token.balanceOf(address(this)) - contractPrice);
}
} else {
revert('e008');
}
} else {
Token wrongToken = Token(_token);
if (wrongToken.balanceOf(address(this)) > 0) {
wrongToken.transfer(msg.sender, wrongToken.balanceOf(address(this)));
} else {
revert('e008');
}
}
}
function balanceOf(address account) external view returns(uint256) {
return token.balanceOf(account);
}
function getBalanceOfContract() public view returns(uint256) {
return token.balanceOf(address(this));
}
function getCurrentTimestamp() public view returns(uint256) {
return block.timestamp;
}
function isContract(address _address) public view returns(bool) {
uint256 size;
assembly { size := extcodesize(_address) }
return size > 0;
}
}
文件 4 的 6:IERC20.sol
pragma solidity 0.8.14;
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);
}
文件 5 的 6:IERC20Metadata.sol
pragma solidity 0.8.14;
import "IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 6 的 6:Token.sol
pragma solidity 0.8.14;
import "ERC20.sol";
contract Token is ERC20 {
constructor(
string memory _name, string memory _symbol
) ERC20(_name, _symbol) {}
function mint(address to, uint256 value) public {
require(value > 0, 'Value must greater than 0');
_mint(to, value);
}
}
{
"compilationTarget": {
"Escrow_v1.0.0.sol": "Escrow_v100"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_buyer","type":"address"},{"internalType":"address","name":"_seller","type":"address"},{"internalType":"address","name":"_agent","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_contractPrice","type":"uint256"},{"internalType":"uint256","name":"_buyerProtectionTime","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ContractState","outputs":[{"internalType":"enum Escrow_v100.ContractStateChoices","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyerProtectionTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"confirmFulfillment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"executionTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBalanceOfContract","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inviteAgent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"returnMoney","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"seller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_agentPercent","type":"uint256"},{"internalType":"uint256","name":"_buyerPercent","type":"uint256"},{"internalType":"uint256","name":"_sellerPercent","type":"uint256"}],"name":"sendMoney","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract Token","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]