文件 1 的 5:EVMBridgeNative.sol
pragma solidity ^0.8.9;
import "./interfaces/IERC20.sol";
import "./utils/TransferHelper.sol";
import "./libs/SafeMath.sol";
import "./libs/SignedSafeMath.sol";
struct Bridge {
address addr;
string chain;
}
struct Validator {
address addr;
uint256 warrantyAmount;
uint256 totalLossAmount;
}
contract EVMBridgeNative {
using SafeMath for uint256;
using SignedSafeMath for int256;
address public owner;
address public program;
string public chain;
uint256 public feesInDollar;
uint256 public defaultFeesInETH;
uint256 public minimumTransferQuantity;
uint256 public bridgeFeesInNative;
event BridgeTransfer(
uint256 amount,
string toChain
);
mapping(address => mapping(uint256 => bool)) transfers;
address private dex_in;
address private dex_out;
address private dex_pool;
bool internal paused;
bool internal locked;
constructor(
string memory _bridgeChain,
address ,
uint256 _feesInDollar,
uint256 _minimumTransferQuantity) {
require(msg.sender != address(0), "ABORT sender - address(0)");
owner = msg.sender;
program = msg.sender;
chain = _bridgeChain;
feesInDollar = _feesInDollar;
minimumTransferQuantity = _minimumTransferQuantity;
defaultFeesInETH = 0;
}
modifier onlyOwner() {
require(msg.sender == owner, "Only the owner can do this action");
_;
}
modifier onlyProgramOrOwner() {
require(msg.sender == program || msg.sender == owner, "Only program or Owner");
_;
}
modifier activated() {
require(paused == false, "Bridge actually paused");
_;
}
modifier noReentrant() {
require(!locked, "No re-entrancy");
locked = true;
_;
locked = false;
}
function getFeesInDollar() public view returns (uint256) {
return feesInDollar;
}
function setFeesInDollar(uint256 cost) public onlyOwner {
feesInDollar = cost;
}
function setDefaultFeesInETH(uint256 cost) public onlyOwner {
defaultFeesInETH = cost;
}
function getFeesInETH() public view returns (uint256) {
if (dex_pool != address(0)) {
uint256 oneDollar = getTokenPriceOutFromPoolBalance(dex_in, dex_out, dex_pool);
return oneDollar.mul(1 ether).div(feesInDollar).mul(100);
}
return defaultFeesInETH;
}
function initTransfer(uint256 quantity, string calldata toChain) public payable noReentrant activated {
require(quantity >= minimumTransferQuantity,
"INSUFISANT_QUANTITY"
);
require(msg.value >= getFeesInETH().mul(90).div(100).add(quantity),
"PAYMENT_ABORT"
);
bridgeFeesInNative += msg.value.sub(quantity);
emit BridgeTransfer(quantity, toChain);
}
function getFees() public view returns (uint256) {
return bridgeFeesInNative;
}
function claimFees() public onlyOwner noReentrant {
(bool success,)=owner.call{value:bridgeFeesInNative}("");
require(success, "BridgeTransfer failed!");
bridgeFeesInNative = 0;
}
function balance() public view returns (uint256){
return payable(address(this)).balance;
}
function depositETH(uint256 quantity) public payable onlyOwner noReentrant {
require(msg.value >= quantity,
"PAYMENT_ABORT"
);
}
function setTransferProcessed(address sender, uint256 transferBn) private {
transfers[sender][transferBn] = true;
}
function isTransferProcessed(address sender, uint256 transferBn) public view returns (bool) {
return transfers[sender][transferBn];
}
function addTransferFrom(address from, uint256 amount, uint256 bn) public onlyProgramOrOwner {
require(isTransferProcessed(from, bn) == false, "Bridge request already processed.");
setTransferProcessed(from, bn);
(bool success,)=from.call{value:amount}("");
require(success, "Transfer failed!");
}
function getDex() public view returns (address, address, address) {
return (dex_in, dex_out, dex_pool);
}
function setDex(address _in, address _out, address _pool) public onlyOwner {
dex_in = _in;
dex_out = _out;
dex_pool = _pool;
}
function getTokenPriceOutFromPoolBalance(address _in, address _out, address _pool) public view returns (uint256) {
uint256 balanceIn = IERC20(_in).balanceOf(_pool);
uint256 balanceOut = IERC20(_out).balanceOf(_pool);
require(balanceOut > 0);
return balanceIn.mul(1 ether).div(balanceOut);
}
function updateTransferCost(uint256 _feesInDollar) public onlyOwner {
feesInDollar = _feesInDollar;
}
function isPaused() public view returns (bool) {
return paused;
}
function setPaused(bool p) public onlyOwner {
paused = p;
}
function setMinimumTransferQuantity(uint256 quantity) public onlyOwner {
minimumTransferQuantity = quantity;
}
function changeOwner(address newOwner) public onlyOwner {
require(newOwner != address(0), "No zero address");
owner = newOwner;
}
function changeProgram(address newProgram) public onlyOwner {
require(newProgram != address(0), "No zero address");
program = newProgram;
}
}
文件 2 的 5:IERC20.sol
pragma solidity ^0.8.9;
interface IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
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:SafeMath.sol
pragma solidity ^0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
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) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
文件 4 的 5:SignedSafeMath.sol
pragma solidity ^0.8.0;
library SignedSafeMath {
function mul(int256 a, int256 b) internal pure returns (int256) {
return a * b;
}
function div(int256 a, int256 b) internal pure returns (int256) {
return a / b;
}
function sub(int256 a, int256 b) internal pure returns (int256) {
return a - b;
}
function add(int256 a, int256 b) internal pure returns (int256) {
return a + b;
}
}
文件 5 的 5:TransferHelper.sol
pragma solidity ^0.8.9;
library TransferHelper {
function safeTransfer(address token, address to, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
}
{
"compilationTarget": {
"contracts/EVMBridgeNative.sol": "EVMBridgeNative"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 10000
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"_bridgeChain","type":"string"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"_feesInDollar","type":"uint256"},{"internalType":"uint256","name":"_minimumTransferQuantity","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"toChain","type":"string"}],"name":"BridgeTransfer","type":"event"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"bn","type":"uint256"}],"name":"addTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"balance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeFeesInNative","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chain","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"changeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newProgram","type":"address"}],"name":"changeProgram","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultFeesInETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"depositETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"feesInDollar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDex","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeesInDollar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeesInETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_in","type":"address"},{"internalType":"address","name":"_out","type":"address"},{"internalType":"address","name":"_pool","type":"address"}],"name":"getTokenPriceOutFromPoolBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"string","name":"toChain","type":"string"}],"name":"initTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"transferBn","type":"uint256"}],"name":"isTransferProcessed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumTransferQuantity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"program","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"cost","type":"uint256"}],"name":"setDefaultFeesInETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_in","type":"address"},{"internalType":"address","name":"_out","type":"address"},{"internalType":"address","name":"_pool","type":"address"}],"name":"setDex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"cost","type":"uint256"}],"name":"setFeesInDollar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"setMinimumTransferQuantity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"p","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feesInDollar","type":"uint256"}],"name":"updateTransferCost","outputs":[],"stateMutability":"nonpayable","type":"function"}]