文件 1 的 4:BridgeVault.sol
pragma solidity ^0.8.0;
import './ECDSA.sol';
import './IERC20.sol';
import './Context.sol';
contract ZefuVaultETH is Context{
using ECDSA for bytes32;
struct Cross {
uint256 nonce;
mapping (uint256 => uint256) amount;
}
mapping(address => Cross) private _transferIn;
mapping(address => Cross) private _transferOut;
IERC20 private ZEFU;
address private _validator;
constructor(IERC20 token, address validator) {
ZEFU = token;
_validator = validator;
}
function vaultBalance() public view returns (uint256) {
return ZEFU.balanceOf(address(this));
}
function getNonceIn(address user) public view returns (uint256) {
return _transferIn[user].nonce;
}
function getNonceOut(address user) public view returns (uint256) {
return _transferOut[user].nonce;
}
function getAmountIn(address user, uint256 nonce) public view returns (uint256) {
return _transferIn[user].amount[nonce];
}
function getAmountOut(address user, uint256 nonce) public view returns (uint256) {
return _transferOut[user].amount[nonce];
}
function getValidator() public view returns (address) {
return _validator;
}
function setValidator(address validator) public {
require(_msgSender() == _validator, "Valut: Invalid Validator.");
_validator = validator;
}
function getHash(address user, uint256 nonce, uint256 amount) public pure returns (bytes32 hash) {
hash = keccak256(abi.encodePacked(user, nonce, amount));
}
function swapToBSC(uint256 amount) public virtual {
address user = _msgSender();
ZEFU.transferFrom(user, address(this), amount);
uint256 nonce = getNonceOut(user);
_transferOut[user].amount[nonce] = amount;
_transferOut[user].nonce++;
}
function swapFromBSC(uint256 amount, bytes memory signature) public virtual {
address user = _msgSender();
uint256 nonce = getNonceIn(user);
bytes32 hash = keccak256(abi.encodePacked(user, nonce, amount));
require(hash.recover(signature) == getValidator(), "Vault: Invalid transaction.");
_transferIn[user].amount[nonce] = amount;
_transferIn[user].nonce++;
ZEFU.transfer(_msgSender(), amount);
}
}
文件 2 的 4:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this;
return msg.data;
}
}
文件 3 的 4:ECDSA.sol
pragma solidity ^0.8.0;
library ECDSA {
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
if (signature.length != 65) {
revert("ECDSA: invalid signature length");
}
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return recover(hash, v, r, s);
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value");
require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value");
address signer = ecrecover(hash, v, r, s);
require(signer != address(0), "ECDSA: invalid signature");
return signer;
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
文件 4 的 4:IERC20.sol
pragma solidity ^0.8.0;
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);
}
{
"compilationTarget": {
"BridgeVault.sol": "ZefuVaultETH"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"validator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getHash","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonceIn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonceOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getValidator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"validator","type":"address"}],"name":"setValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"swapFromBSC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"swapToBSC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]