Address Contract Verified
Address
0x8fF3B24225f13c301983909990cF10dAE8a33dA3
Balance
0 ETH
Nonce
1
Code Size
4689 bytes
Creator
0x6C1e7867...5785 at tx 0x23cc5915...266c11
Indexed Transactions
0
Contract Bytecode
4689 bytes
0x60806040526004361061007f5760003560e01c80637c19f0051161004e5780637c19f0051461014c5780638da5cb5b14610180578063a6f9dae1146101a0578063feaea586146101c057610086565b8063256b5a021461008b57806335aa6df8146100ad5780634f64b2be146100fe5780635b41b9081461011e57610086565b3661008657005b600080fd5b34801561009757600080fd5b506100ab6100a6366004611076565b6101e0565b005b3480156100b957600080fd5b506100e17f0000000000000000000000000ec9b7ef4c071bbcc8ac47b79eba7646d4c1498a81565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561010a57600080fd5b506100e161011936600461113d565b610429565b34801561012a57600080fd5b5061013e61013936600461116d565b610453565b6040519081526020016100f5565b34801561015857600080fd5b506100e17f000000000000000000000000abea9132b05a70803a4e85094fd0e1800777fbef81565b34801561018c57600080fd5b506000546100e1906001600160a01b031681565b3480156101ac57600080fd5b506100ab6101bb366004611076565b6108f2565b3480156101cc57600080fd5b5061013e6101db3660046110b5565b6109f9565b6000546001600160a01b0316331461022e5760405162461bcd60e51b815260206004820152600c60248201526b1d5b985d5d1a1bdc9a5cd95960a21b60448201526064015b60405180910390fd5b6001600160a01b0381166102845760405162461bcd60e51b815260206004820152600c60248201527f6e756c6c207976546f6b656e00000000000000000000000000000000000000006044820152606401610225565b6000816001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102bf57600080fd5b505afa1580156102d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f79190611099565b90506001600160a01b03811661034f5760405162461bcd60e51b815260206004820152600a60248201527f6e756c6c20746f6b656e000000000000000000000000000000000000000000006044820152606401610225565b60018054808201825560008290527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690810180546001600160a01b0380861673ffffffffffffffffffffffffffffffffffffffff199283161790925583548085018555909201805491861691909216179055546103ce906002906111cd565b156103e957634e487b7160e01b600052600160045260246000fd5b6040516001600160a01b03831681527f7b7ef7a864d96a85497a1ed846adb39940dd6ccef678ff6ac8d55505e09b8cc49060200160405180910390a15050565b6001818154811061043957600080fd5b6000918252602090912001546001600160a01b0316905081565b600080546001600160a01b0316331461049d5760405162461bcd60e51b815260206004820152600c60248201526b1d5b985d5d1a1bdc9a5cd95960a21b6044820152606401610225565b60015485106104ee5760405162461bcd60e51b815260206004820152601360248201527f696e76616c696420696e70757420696e646578000000000000000000000000006044820152606401610225565b600154841080156104ff5750848414155b61054b5760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206f757470757420696e6465780000000000000000000000006044820152606401610225565b60006001868154811061056e57634e487b7160e01b600052603260045260246000fd5b6000918252602082200154600180546001600160a01b03909216935090879081106105a957634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b031690506105c982610c35565b6105d46002886111cd565b61074e576105e387600161119e565b86146106315760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206f757470757420746f6b656e0000000000000000000000006044820152606401610225565b60405163095ea7b360e01b81526001600160a01b0382811660048301526024820187905283169063095ea7b390604401602060405180830381600087803b15801561067b57600080fd5b505af115801561068f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b391906110ed565b506040517fb6b55f25000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b0382169063b6b55f2590602401602060405180830381600087803b15801561070f57600080fd5b505af1158015610723573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107479190611155565b925061083d565b6107596001886111b6565b86146107a75760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206f757470757420746f6b656e0000000000000000000000006044820152606401610225565b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b03831690632e1a7d4d90602401602060405180830381600087803b15801561080257600080fd5b505af1158015610816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083a9190611155565b92505b8383101561088d5760405162461bcd60e51b815260206004820152600860248201527f736c6970706167650000000000000000000000000000000000000000000000006044820152606401610225565b6108978184610dc4565b604080516001600160a01b038481168252602082018890528316818301526060810185905290517fdb587d878116df0bdd4fe154699aa2c5f439da001cc811dfd05d9f589fc5a8ee9181900360800190a15050949350505050565b6000546001600160a01b0316331461093b5760405162461bcd60e51b815260206004820152600c60248201526b1d5b985d5d1a1bdc9a5cd95960a21b6044820152606401610225565b6001600160a01b0381166109915760405162461bcd60e51b815260206004820152600d60248201527f696e76616c696420696e707574000000000000000000000000000000000000006044820152606401610225565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040805182815260208101929092527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a150565b600080546001600160a01b03163314610a435760405162461bcd60e51b815260206004820152600c60248201526b1d5b985d5d1a1bdc9a5cd95960a21b6044820152606401610225565b60006001600160a01b038316610aaf576040514792506001600160a01b038516908390600081818185875af1925050503d8060008114610a9f576040519150601f19603f3d011682016040523d82523d6000602084013e610aa4565b606091505b505080915050610be1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038416906370a082319060240160206040518083038186803b158015610b0757600080fd5b505afa158015610b1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3f9190611155565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152602482018390529193509084169063a9059cbb90604401602060405180830381600087803b158015610ba657600080fd5b505af1158015610bba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bde91906110ed565b90505b80610c2e5760405162461bcd60e51b815260206004820152601160248201527f6661696c656420746f207265636f7665720000000000000000000000000000006044820152606401610225565b5092915050565b6040517f5aca41f60000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0382811660248301526000917f000000000000000000000000abea9132b05a70803a4e85094fd0e1800777fbef90911690635aca41f69060440160206040518083038186803b158015610cba57600080fd5b505afa158015610cce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf2919061110d565b90506fffffffffffffffffffffffffffffffff811615610dc0576040517fd514da500000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0383811660248301526fffffffffffffffffffffffffffffffff831660448301527f000000000000000000000000abea9132b05a70803a4e85094fd0e1800777fbef169063d514da50906064015b600060405180830381600087803b158015610da757600080fd5b505af1158015610dbb573d6000803e3d6000fd5b505050505b5050565b6001600160a01b038216610e8d576040517f2d2da8060000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000ec9b7ef4c071bbcc8ac47b79eba7646d4c1498a811660048301527f000000000000000000000000abea9132b05a70803a4e85094fd0e1800777fbef1690632d2da8069083906024016000604051808303818588803b158015610e6f57600080fd5b505af1158015610e83573d6000803e3d6000fd5b5050505050610dc0565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000abea9132b05a70803a4e85094fd0e1800777fbef811660048301526024820183905283169063095ea7b390604401602060405180830381600087803b158015610ef757600080fd5b505af1158015610f0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2f91906110ed565b507f000000000000000000000000abea9132b05a70803a4e85094fd0e1800777fbef6001600160a01b031663e17376b583610f6984610fed565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b0392831660048201526cffffffffffffffffffffffffff90911660248201527f0000000000000000000000000ec9b7ef4c071bbcc8ac47b79eba7646d4c1498a919091166044820152606401610d8d565b60006cffffffffffffffffffffffffff8211156110725760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201527f30342062697473000000000000000000000000000000000000000000000000006064820152608401610225565b5090565b600060208284031215611087578081fd5b813561109281611203565b9392505050565b6000602082840312156110aa578081fd5b815161109281611203565b600080604083850312156110c7578081fd5b82356110d281611203565b915060208301356110e281611203565b809150509250929050565b6000602082840312156110fe578081fd5b81518015158114611092578182fd5b60006020828403121561111e578081fd5b81516fffffffffffffffffffffffffffffffff81168114611092578182fd5b60006020828403121561114e578081fd5b5035919050565b600060208284031215611166578081fd5b5051919050565b60008060008060808587031215611182578182fd5b5050823594602084013594506040840135936060013592509050565b600082198211156111b1576111b16111ed565b500190565b6000828210156111c8576111c86111ed565b500390565b6000826111e857634e487b7160e01b81526012600452602481fd5b500690565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461121857600080fd5b5056fea26469706673582212202b3b79e3f8ea699efe9141fd8198b4580fca71929a0117846ff398f72ab7690664736f6c63430008030033
Verified Source Code Full Match
Compiler: v0.8.3+commit.8d00100c
EVM: istanbul
Optimization: Yes (1000 runs)
YearnBridgeSwapper.sol 75 lines
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.3;
import "./ZkSyncBridgeSwapper.sol";
import "./interfaces/IYearnVault.sol";
/**
* @notice Exchanges tokens for their respective Yearn vault tokens.
* NOTE: to add a new vault, put the underlying token at the even index,
* immediately followed by the vault token at the odd index.
* Example indexes:
* 0: DAI
* 1: yvDAI
* 2: USDC
* 3: yvUSDC
*/
contract YearnBridgeSwapper is ZkSyncBridgeSwapper {
address[] public tokens;
event VaultAdded(address yvToken);
constructor(address _zkSync, address _l2Account, address[] memory _yvTokens) ZkSyncBridgeSwapper(_zkSync, _l2Account) {
for (uint i = 0; i < _yvTokens.length; i++) {
addVault(_yvTokens[i]);
}
}
function exchange(
uint256 _indexIn,
uint256 _indexOut,
uint256 _amountIn,
uint256 _minAmountOut
)
onlyOwner
external
override
returns (uint256 amountOut)
{
require(_indexIn < tokens.length, "invalid input index");
require(_indexOut < tokens.length && _indexOut != _indexIn, "invalid output index");
address inputToken = tokens[_indexIn];
address outputToken = tokens[_indexOut];
transferFromZkSync(inputToken);
if (_indexIn % 2 == 0) { // deposit
require(_indexOut == _indexIn + 1, "invalid output token");
IERC20(inputToken).approve(outputToken, _amountIn);
amountOut = IYearnVault(outputToken).deposit(_amountIn);
} else { // withdrawal
require(_indexOut == _indexIn - 1, "invalid output token");
amountOut = IYearnVault(inputToken).withdraw(_amountIn);
}
require(amountOut >= _minAmountOut, "slippage");
transferToZkSync(outputToken, amountOut);
emit Swapped(inputToken, _amountIn, outputToken, amountOut);
}
function addVault(address _yvToken) public onlyOwner {
require(_yvToken != address(0), "null yvToken");
address token = IYearnVault(_yvToken).token();
require(token != address(0), "null token");
tokens.push(token);
tokens.push(_yvToken);
assert(tokens.length % 2 == 0);
emit VaultAdded(_yvToken);
}
}
IZkSync.sol 11 lines
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IZkSync {
function getPendingBalance(address _address, address _token) external view returns (uint128);
function withdrawPendingBalance(address payable _owner, address _token, uint128 _amount) external;
function depositETH(address _zkSyncAddress) external payable;
function depositERC20(IERC20 _token, uint104 _amount, address _zkSyncAddress) external;
}
ZkSyncBridgeSwapper.sol 99 lines
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.3;
import "./interfaces/IZkSync.sol";
import "./interfaces/IBridgeSwapper.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
abstract contract ZkSyncBridgeSwapper is IBridgeSwapper {
// The owner of the contract
address public owner;
// The ZkSync bridge contract
address public immutable zkSync;
// The L2 market maker account
address public immutable l2Account;
address constant internal ETH_TOKEN = address(0);
event OwnerChanged(address _owner, address _newOwner);
event SlippageChanged(uint256 _slippagePercent);
modifier onlyOwner {
require(msg.sender == owner, "unauthorised");
_;
}
constructor(address _zkSync, address _l2Account) {
zkSync = _zkSync;
l2Account = _l2Account;
owner = msg.sender;
}
function changeOwner(address _newOwner) external onlyOwner {
require(_newOwner != address(0), "invalid input");
owner = _newOwner;
emit OwnerChanged(owner, _newOwner);
}
/**
* @dev Check if there is a pending balance to withdraw in zkSync and withdraw it if applicable.
* @param _token The token to withdraw.
*/
function transferFromZkSync(address _token) internal {
uint128 pendingBalance = IZkSync(zkSync).getPendingBalance(address(this), _token);
if (pendingBalance > 0) {
IZkSync(zkSync).withdrawPendingBalance(payable(address(this)), _token, pendingBalance);
}
}
/**
* @dev Deposit the ETH or ERC20 token to zkSync.
* @param _outputToken The token that was given.
* @param _amountOut The amount of given token.
*/
function transferToZkSync(address _outputToken, uint256 _amountOut) internal {
if (_outputToken == ETH_TOKEN) {
// deposit Eth to L2 bridge
IZkSync(zkSync).depositETH{value: _amountOut}(l2Account);
} else {
// approve the zkSync bridge to take the output token
IERC20(_outputToken).approve(zkSync, _amountOut);
// deposit the output token to the L2 bridge
IZkSync(zkSync).depositERC20(IERC20(_outputToken), toUint104(_amountOut), l2Account);
}
}
/**
* @dev Safety method to recover ETH or ERC20 tokens that are sent to the contract by error.
* @param _token The token to recover.
*/
function recoverToken(address _recipient, address _token) external onlyOwner returns (uint256 balance) {
bool success;
if (_token == ETH_TOKEN) {
balance = address(this).balance;
(success, ) = _recipient.call{value: balance}("");
} else {
balance = IERC20(_token).balanceOf(address(this));
success = IERC20(_token).transfer(_recipient, balance);
}
require(success, "failed to recover");
}
/**
* @dev fallback method to make sure we can receive ETH
*/
receive() external payable {
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*/
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
}
IYearnVault.sol 10 lines
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.3;
interface IYearnVault {
function token() external view returns (address);
function pricePerShare() external view returns (uint256);
function deposit(uint256 _amount) external returns (uint256);
function withdraw(uint256 _maxShares) external returns (uint256);
}
IBridgeSwapper.sol 16 lines
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.3;
interface IBridgeSwapper {
event Swapped(address _inputToken, uint256 _amountIn, address _outputToken, uint256 _amountOut);
/**
* @notice Perform an exchange between two tokens
* @dev Index values can usually be found via the constructor arguments (if not hardcoded)
* @param _indexIn Index value for the token to send
* @param _indexOut Index valie of the token to receive
* @param _amountIn Amount of `_indexIn` being exchanged
* @return Actual amount of `_indexOut` received
*/
function exchange(uint256 _indexIn, uint256 _indexOut, uint256 _amountIn, uint256 _minAmountOut) external returns (uint256);
}
IERC20.sol 82 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
Read Contract
l2Account 0x35aa6df8 → address
owner 0x8da5cb5b → address
tokens 0x4f64b2be → address
zkSync 0x7c19f005 → address
Write Contract 4 functions
These functions modify contract state and require a wallet transaction to execute.
addVault 0x256b5a02
address _yvToken
changeOwner 0xa6f9dae1
address _newOwner
exchange 0x5b41b908
uint256 _indexIn
uint256 _indexOut
uint256 _amountIn
uint256 _minAmountOut
returns: uint256
recoverToken 0xfeaea586
address _recipient
address _token
returns: uint256
Recent Transactions
No transactions found for this address