Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WETH address as argument instead of hardcoded (solver's contract) #46

Merged
merged 6 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions script/base/deploy-base.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {TxBuilder} from "src/contracts/helpers/TxBuilder.sol";
import {Simulator} from "src/contracts/helpers/Simulator.sol";
import {SimpleRFQSolver} from "test/SwapIntent.t.sol";

import {Utilities} from "src/contracts/helpers/Utilities.sol";

contract DeployBaseScript is Script {
using stdJson for string;

Expand All @@ -33,6 +35,8 @@ contract DeployBaseScript is Script {
TxBuilder public txBuilder;
SimpleRFQSolver public rfqSolver;

Utilities public u;

function _getDeployChain() internal view returns (string memory) {
// OPTIONS: LOCAL, SEPOLIA, MAINNET
string memory deployChain = vm.envString("DEPLOY_TO");
Expand Down
6 changes: 5 additions & 1 deletion script/deploy-solver.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ contract DeploySimpleRFQSolverScript is DeployBaseScript {
uint256 deployerPrivateKey = vm.envUint("SOLVER1_PRIVATE_KEY");
address deployer = vm.addr(deployerPrivateKey);
address atlasAddress = _getAddressFromDeploymentsJson("ATLAS");
address wethAddress = u.getUsefulContractAddress(vm.envString("DEPLOY_TO"), "WETH");

console.log("Deployer address: \t\t\t\t", deployer);
console.log("Using Atlas address: \t\t\t\t", atlasAddress);

vm.startBroadcast(deployerPrivateKey);

rfqSolver = new SimpleRFQSolver(atlasAddress);
rfqSolver = new SimpleRFQSolver({
weth: wethAddress,
atlas: atlasAddress
});

vm.stopBroadcast();

Expand Down
23 changes: 23 additions & 0 deletions src/contracts/helpers/Utilities.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import "forge-std/Script.sol";
import "forge-std/Test.sol";
import "forge-std/StdJson.sol";

contract Utilities is Script{
using stdJson for string;

function getUsefulContractAddress(string memory chain, string memory key) public view returns (address) {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/useful-addresses.json");
string memory json = vm.readFile(path);
string memory fullKey = string.concat(".", chain, ".", key);

address res = json.readAddress(fullKey);
if (res == address(0x0000000000000000000000000000000000000020)) {
revert(string.concat(fullKey, " not found in useful-addresses.json"));
}
return res;
}
}
32 changes: 15 additions & 17 deletions src/contracts/solver/SolverBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,25 @@ interface IWETH9 {
}

contract SolverBase is Test {
address public constant WETH_ADDRESS = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
address public immutable WETH_ADDRESS;

// TODO consider making these accessible (internal) for solvers which may want to use them
address private immutable _owner;
address private immutable _escrow;

constructor(address atlasEscrow, address owner) {
constructor(address weth, address atlasEscrow, address owner) {
WETH_ADDRESS = weth;
_owner = owner;
_escrow = atlasEscrow;
}

function atlasSolverCall(address sender, address bidToken, uint256 bidAmount, bytes calldata solverOpData, bytes calldata extraReturnData)
external
payable
safetyFirst(sender)
payBids(bidToken, bidAmount)
returns (bool success, bytes memory data)
{
function atlasSolverCall(
address sender,
address bidToken,
uint256 bidAmount,
bytes calldata solverOpData,
bytes calldata extraReturnData
) external payable safetyFirst(sender) payBids(bidToken, bidAmount) returns (bool success, bytes memory data) {
(success, data) = address(this).call{value: msg.value}(solverOpData);

require(success, "CALL UNSUCCESSFUL");
Expand All @@ -43,36 +44,33 @@ contract SolverBase is Test {
// Safety checks
require(sender == _owner, "INVALID CALLER");
// uint256 msgValueOwed = msg.value;

_;

IEscrow(_escrow).reconcile{value: msg.value}(msg.sender, sender, type(uint256).max);
}

modifier payBids(address bidToken, uint256 bidAmount) {
// Track starting balances

uint256 bidBalance = bidToken == address(0) ?
address(this).balance - msg.value :
ERC20(bidToken).balanceOf(address(this));

uint256 bidBalance =
bidToken == address(0) ? address(this).balance - msg.value : ERC20(bidToken).balanceOf(address(this));

_;

// Handle bid payment

// Ether balance
if (bidToken == address(0)) {

uint256 ethOwed = bidAmount + msg.value;

if (ethOwed > address(this).balance) {
IWETH9(WETH_ADDRESS).withdraw(ethOwed - address(this).balance);

}

SafeTransferLib.safeTransferETH(msg.sender, bidAmount);

// ERC20 balance
// ERC20 balance
} else {
if (msg.value > address(this).balance) {
IWETH9(WETH_ADDRESS).withdraw(msg.value - address(this).balance);
Expand Down
2 changes: 1 addition & 1 deletion src/contracts/solver/src/TestSolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ import {SolverBase} from "../SolverBase.sol";
import {BlindBackrun} from "./BlindBackrun/BlindBackrun.sol";

contract Solver is SolverBase, BlindBackrun {
constructor(address atlasEscrow, address owner) SolverBase(atlasEscrow, owner) {}
constructor(address weth9, address atlasEscrow, address owner) SolverBase(weth9, atlasEscrow, owner) {}
}
8 changes: 4 additions & 4 deletions test/Accounting.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ contract AccountingTest is BaseTest {

// Solver deploys the RFQ solver contract (defined at bottom of this file)
vm.startPrank(solverOneEOA);
HonestRFQSolver honestSolver = new HonestRFQSolver(address(atlas));
HonestRFQSolver honestSolver = new HonestRFQSolver(WETH_ADDRESS, address(atlas));
vm.stopPrank();

SolverOperation[] memory solverOps = _setupBorrowRepayTestUsingBasicSwapIntent(address(honestSolver));
Expand Down Expand Up @@ -100,7 +100,7 @@ contract AccountingTest is BaseTest {
// Solver deploys the RFQ solver contract (defined at bottom of this file)
vm.startPrank(solverOneEOA);
// TODO make evil solver
HonestRFQSolver evilSolver = new HonestRFQSolver(address(atlas));
HonestRFQSolver evilSolver = new HonestRFQSolver(WETH_ADDRESS, address(atlas));
// atlas.deposit{value: gasCostCoverAmount}(solverOneEOA);
vm.stopPrank();

Expand Down Expand Up @@ -237,7 +237,7 @@ contract AccountingTest is BaseTest {
// This might involve an offchain RFQ system
contract HonestRFQSolver is SolverBase {
address public immutable ATLAS;
constructor(address atlas) SolverBase(atlas, msg.sender) {
constructor(address weth9, address atlas) SolverBase(weth9, atlas, msg.sender) {
ATLAS = atlas;
}

Expand All @@ -264,7 +264,7 @@ contract HonestRFQSolver is SolverBase {

contract EvilRFQSolver is HonestRFQSolver {
address deployer;
constructor(address atlas) HonestRFQSolver(atlas) {
constructor(address weth9, address atlas) HonestRFQSolver(weth9, atlas) {
deployer = msg.sender;
}
function fulfillRFQ(
Expand Down
25 changes: 4 additions & 21 deletions test/SwapIntent.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,6 @@ import {DAppOperation, DAppConfig} from "../src/contracts/types/DAppApprovalType
import {SwapIntentController, SwapIntent, Condition} from "../src/contracts/examples/intents-example/SwapIntent.sol";
import {SolverBase} from "../src/contracts/solver/SolverBase.sol";

// QUESTIONS:

// Refactor Ideas:
// 1. Lots of bitwise operations explicitly coded in contracts - could be a helper lib thats more readable
// 2. helper is currently a V2Helper and shared from BaseTest. Should only be in Uni V2 related tests
// 3. Need a more generic helper for BaseTest
// 4. Gonna be lots of StackTooDeep errors. Maybe need a way to elegantly deal with that in BaseTest
// 5. Change atlasSolverCall structure in SolverBase - maybe virtual fn to be overridden, which hooks for checks
// 6. Maybe emit error msg or some other better UX for error if !valid in metacall()

// Doc Ideas:
// 1. Step by step instructions for building a metacall transaction (for internal testing, and integrating dApps)

// To Understand Better:
// 1. The lock system (and look for any gas optimizations / ways to reduce lock actions)


interface IUniV2Router02 {
function swapExactTokensForTokens(
Expand Down Expand Up @@ -83,7 +67,6 @@ contract SwapIntentTest is BaseTest {

function testAtlasSwapIntentWithBasicRFQ() public {
// Swap 10 WETH for 20 DAI

UserCondition userCondition = new UserCondition();

Condition[] memory conditions = new Condition[](2);
Expand All @@ -108,7 +91,7 @@ contract SwapIntentTest is BaseTest {

// Solver deploys the RFQ solver contract (defined at bottom of this file)
vm.startPrank(solverOneEOA);
SimpleRFQSolver rfqSolver = new SimpleRFQSolver(address(atlas));
SimpleRFQSolver rfqSolver = new SimpleRFQSolver(WETH_ADDRESS, address(atlas));
atlas.deposit{value: 1e18}();
vm.stopPrank();

Expand Down Expand Up @@ -234,7 +217,7 @@ contract SwapIntentTest is BaseTest {

// Solver deploys the RFQ solver contract (defined at bottom of this file)
vm.startPrank(solverOneEOA);
UniswapIntentSolver uniswapSolver = new UniswapIntentSolver(address(atlas));
UniswapIntentSolver uniswapSolver = new UniswapIntentSolver(WETH_ADDRESS, address(atlas));
deal(WETH_ADDRESS, address(uniswapSolver), 1e18); // 1 WETH to solver to pay bid
atlas.deposit{value: 1e18}();
vm.stopPrank();
Expand Down Expand Up @@ -349,7 +332,7 @@ contract SwapIntentTest is BaseTest {
// This solver magically has the tokens needed to fulfil the user's swap.
// This might involve an offchain RFQ system
contract SimpleRFQSolver is SolverBase {
constructor(address atlas) SolverBase(atlas, msg.sender) {}
constructor(address weth, address atlas) SolverBase(weth, atlas, msg.sender) {}

function fulfillRFQ(
SwapIntent calldata swapIntent,
Expand All @@ -374,7 +357,7 @@ contract SimpleRFQSolver is SolverBase {
contract UniswapIntentSolver is SolverBase {
IUniV2Router02 router = IUniV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);

constructor(address atlas) SolverBase(atlas, msg.sender) {}
constructor(address weth, address atlas) SolverBase(weth, atlas, msg.sender) {}

function fulfillWithSwap(
SwapIntent calldata swapIntent,
Expand Down
9 changes: 7 additions & 2 deletions test/base/BaseTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {TestConstants} from "./TestConstants.sol";

import {V2Helper} from "../V2Helper.sol";

import {Utilities} from "src/contracts/helpers/Utilities.sol";

contract BaseTest is Test, TestConstants {
address public me = address(this);

Expand Down Expand Up @@ -57,6 +59,8 @@ contract BaseTest is Test, TestConstants {

V2Helper public helper;

Utilities public u;

// Fork stuff
ChainVars public chain = mainnet;
uint256 public forkNetwork;
Expand Down Expand Up @@ -139,7 +143,7 @@ contract BaseTest is Test, TestConstants {

vm.startPrank(solverOneEOA);

solverOne = new Solver(escrow, solverOneEOA);
solverOne = new Solver(WETH_ADDRESS, escrow, solverOneEOA);
atlas.deposit{value: 1e18}();

deal(TOKEN_ZERO, address(solverOne), 10e24);
Expand All @@ -149,7 +153,7 @@ contract BaseTest is Test, TestConstants {

vm.startPrank(solverTwoEOA);

solverTwo = new Solver(escrow, solverTwoEOA);
solverTwo = new Solver(WETH_ADDRESS, escrow, solverTwoEOA);
atlas.deposit{value: 1e18}();

vm.stopPrank();
Expand All @@ -158,6 +162,7 @@ contract BaseTest is Test, TestConstants {
deal(TOKEN_ONE, address(solverTwo), 10e24);

helper = new V2Helper(address(control), address(atlas), address(atlasVerification));
u = new Utilities();

deal(TOKEN_ZERO, address(atlas), 1);
deal(TOKEN_ONE, address(atlas), 1);
Expand Down
14 changes: 11 additions & 3 deletions test/base/TestConstants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,23 @@ import {IUniswapV2Pair} from "../../src/contracts/examples/v2-example/interfaces
contract TestConstants {
uint256 public constant BLOCK_START = 17441786;

// MAINNET
ChainVars public mainnet = ChainVars({rpcUrlKey: "MAINNET_RPC_URL", forkBlock: BLOCK_START});

// Structs
struct ChainVars {
string rpcUrlKey;
uint256 forkBlock;
address weth;
address dai;
}

// MAINNET
ChainVars public mainnet = ChainVars({
rpcUrlKey: "MAINNET_RPC_URL",
forkBlock: BLOCK_START,
weth: address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2),
dai: address(0x6B175474E89094C44Da98b954EedeAC495271d0F)
});


// Constants
address public constant FXS_ADDRESS = address(0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0);
address public constant WETH_ADDRESS = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
Expand Down
16 changes: 16 additions & 0 deletions useful-addresses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"MAINNET": {
"WETH": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"DAI": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"USDC": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"UNI": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
"UNISWAP_V2_ROUTER": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"
},
"SEPOLIA": {
"WETH": "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
"DAI": "",
"USDC": "",
"UNI": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
"UNISWAP_V2_ROUTER": "0x8f1dD60dBDb493DD940a44985AB43FB9901dcd2e"
}
}