编译器
0.8.10+commit.fc410830
文件 1 的 8:IERC20.sol
pragma solidity 0.8.10;
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);
}
文件 2 的 8:IThorchainRouter.sol
pragma solidity 0.8.10;
interface IThorchainRouter {
function depositWithExpiry(
address payable vault,
address asset,
uint amount,
string memory memo,
uint expiration
) external payable;
}
文件 3 的 8:Owners.sol
pragma solidity 0.8.10;
abstract contract Owners {
event OwnerSet(address indexed owner, bool active);
mapping(address => bool) public owners;
modifier isOwner() {
require(owners[msg.sender], "Unauthorized");
_;
}
function _setOwner(address owner, bool active) internal virtual {
owners[owner] = active;
emit OwnerSet(owner, active);
}
function setOwner(address owner, bool active) public virtual isOwner {
_setOwner(owner, active);
}
}
文件 4 的 8:ReentrancyGuard.sol
pragma solidity >=0.8.0;
abstract contract ReentrancyGuard {
uint256 private locked = 1;
modifier nonReentrant() {
require(locked == 1, "REENTRANCY");
locked = 2;
_;
locked = 1;
}
}
文件 5 的 8:SafeTransferLib.sol
pragma solidity >=0.8.0;
library SafeTransferLib {
function safeTransferETH(address to, uint256 amount) internal {
bool callStatus;
assembly {
callStatus := call(gas(), to, amount, 0, 0, 0, 0)
}
require(callStatus, "ETH_TRANSFER_FAILED");
}
function safeTransferFrom(
address token,
address from,
address to,
uint256 amount
) internal {
bool callStatus;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 68), amount)
callStatus := call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)
}
require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FROM_FAILED");
}
function safeTransfer(
address token,
address to,
uint256 amount
) internal {
bool callStatus;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), amount)
callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)
}
require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FAILED");
}
function safeApprove(
address token,
address to,
uint256 amount
) internal {
bool callStatus;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), amount)
callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)
}
require(didLastOptionalReturnCallSucceed(callStatus), "APPROVE_FAILED");
}
function didLastOptionalReturnCallSucceed(bool callStatus) private pure returns (bool success) {
assembly {
let returnDataSize := returndatasize()
if iszero(callStatus) {
returndatacopy(0, 0, returnDataSize)
revert(0, returnDataSize)
}
switch returnDataSize
case 32 {
returndatacopy(0, 0, returnDataSize)
success := iszero(iszero(mload(0)))
}
case 0 {
success := 1
}
default {
success := 0
}
}
}
}
文件 6 的 8:TSAggregator.sol
pragma solidity 0.8.10;
import { SafeTransferLib } from "../lib/SafeTransferLib.sol";
import { ReentrancyGuard } from "../lib/ReentrancyGuard.sol";
import { Owners } from "./Owners.sol";
import { TSAggregatorTokenTransferProxy } from './TSAggregatorTokenTransferProxy.sol';
abstract contract TSAggregator is Owners, ReentrancyGuard {
using SafeTransferLib for address;
event FeeSet(uint256 fee, address feeRecipient);
uint256 public fee;
address public feeRecipient;
TSAggregatorTokenTransferProxy public tokenTransferProxy;
constructor(address _tokenTransferProxy) {
_setOwner(msg.sender, true);
tokenTransferProxy = TSAggregatorTokenTransferProxy(_tokenTransferProxy);
}
receive() external payable {}
function setFee(uint256 _fee, address _feeRecipient) public isOwner {
require(_fee <= 1000, "fee can not be more than 10%");
fee = _fee;
feeRecipient = _feeRecipient;
emit FeeSet(_fee, _feeRecipient);
}
function skimFee(uint256 amount) internal returns (uint256) {
if (fee != 0 && feeRecipient != address(0)) {
uint256 feeAmount = (amount * fee) / 10000;
feeRecipient.safeTransferETH(feeAmount);
amount -= feeAmount;
}
return amount;
}
}
文件 7 的 8:TSAggregatorGeneric.sol
pragma solidity 0.8.10;
import { SafeTransferLib } from "../lib/SafeTransferLib.sol";
import { TSAggregator } from "./TSAggregator.sol";
import { IERC20 } from "./interfaces/IERC20.sol";
import { IThorchainRouter } from "./interfaces/IThorchainRouter.sol";
import { TSAggregatorTokenTransferProxy } from './TSAggregatorTokenTransferProxy.sol';
contract TSAggregatorGeneric is TSAggregator {
using SafeTransferLib for address;
constructor(address _ttp) TSAggregator(_ttp) {
}
function swapIn(
address tcRouter,
address tcVault,
string calldata tcMemo,
address token,
uint amount,
address router,
bytes calldata data,
uint deadline
) public nonReentrant {
require(router != address(tokenTransferProxy), "no calling ttp");
tokenTransferProxy.transferTokens(token, msg.sender, address(this), amount);
token.safeApprove(address(router), 0);
token.safeApprove(address(router), amount);
(bool success,) = router.call(data);
require(success, "failed to swap");
uint256 amountOut = address(this).balance;
amountOut = skimFee(amountOut);
IThorchainRouter(tcRouter).depositWithExpiry{value: amountOut}(
payable(tcVault),
address(0),
amountOut,
tcMemo,
deadline
);
}
}
文件 8 的 8:TSAggregatorTokenTransferProxy.sol
pragma solidity 0.8.10;
import { SafeTransferLib } from "../lib/SafeTransferLib.sol";
import { Owners } from "./Owners.sol";
contract TSAggregatorTokenTransferProxy is Owners {
using SafeTransferLib for address;
constructor() {
_setOwner(msg.sender, true);
}
function transferTokens(address token, address from, address to, uint256 amount) external isOwner {
require(from == tx.origin || _isContract(from), "Invalid from address");
token.safeTransferFrom(from, to, amount);
}
function _isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
}
{
"compilationTarget": {
"src/TSAggregatorGeneric.sol": "TSAggregatorGeneric"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 10000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_ttp","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"address","name":"feeRecipient","type":"address"}],"name":"FeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"OwnerSet","type":"event"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"owners","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"address","name":"_feeRecipient","type":"address"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"active","type":"bool"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tcRouter","type":"address"},{"internalType":"address","name":"tcVault","type":"address"},{"internalType":"string","name":"tcMemo","type":"string"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"router","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenTransferProxy","outputs":[{"internalType":"contract TSAggregatorTokenTransferProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]