Skip to content

Commit

Permalink
Merge pull request #46 from FastLane-Labs/weth-address
Browse files Browse the repository at this point in the history
WETH address as argument instead of hardcoded (solver's contract)
  • Loading branch information
BenSparksCode authored Nov 16, 2023
2 parents 335e548 + b98bafe commit 9a4fe95
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 49 deletions.
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"
}
}

0 comments on commit 9a4fe95

Please sign in to comment.