Skip to content

Commit

Permalink
allow swaps to be done on behalf of user via signed messages #8
Browse files Browse the repository at this point in the history
  • Loading branch information
bitcoinwarrior1 committed May 2, 2021
1 parent 3fbfdd7 commit 21f7c32
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 80 deletions.
52 changes: 52 additions & 0 deletions contracts/DCAManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
pragma solidity ^0.8.0;

import "./interfaces/IDCAManager.sol";
import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';

contract DCAManager is IDCAManager {

IUniswapV2Router02 public uniswapRouter;

constructor(address _uniswapV2Router) public {
uniswapRouter = IUniswapV2Router02(_uniswapV2Router);
}

/*
* See IDCAManager.sol
*/
function swapOnUsersBehalf(
address baseToken,
uint amountBaseToken,
address destinationToken,
uint fromTime,
uint toTime,
uint8 v,
bytes32 r,
bytes32 s
) public override returns (bool) {
require(block.timestamp >= fromTime && block.timestamp <= toTime, "failed to meet the time requirement");
// TODO have to be careful with this, if signed by a user via metamask it will add the ethereum message prefix
bytes memory message = abi.encodePacked(
baseToken,
amountBaseToken,
destinationToken,
fromTime,
toTime
);
bytes32 messageHash = keccak256(message);
address user = ecrecover(messageHash, v, r, s);
address[] memory path = new address[](2);
path[0] = baseToken;
path[1] = destinationToken;

uniswapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amountBaseToken,
0, // TODO set min amount of WETH using some kind of oracle
path,
user,
toTime
);
return true;
}

}
23 changes: 0 additions & 23 deletions contracts/Greeter.sol

This file was deleted.

29 changes: 29 additions & 0 deletions contracts/interfaces/IDCAManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pragma solidity ^0.8.0;

interface IDCAManager {

/*
* @dev allow a relayer to trigger a trade on behalf of a user with their signed permission,
* requires that the user approve this contract to move the base token
* @param baseToken - the token to trade from
* @param amountBaseToken - the amount of the base token to trade into the destination token
* @param destinationToken - the address of the token that the user wants to swap their base token into
* @param fromTime - the desired time for this swap to occur
* @param toTime - this swap should happen no later than this
* @param v - signature param
* @param r - signature param
* @param s - signature param
* @returns true if successful
*/
function swapOnUsersBehalf(
address baseToken,
uint amountBaseToken,
address destinationToken,
uint fromTime,
uint toTime,
uint8 v,
bytes32 r,
bytes32 s
) external returns (bool);

}
12 changes: 1 addition & 11 deletions hardhat.config.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
require("@nomiclabs/hardhat-waffle");

// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async () => {
const accounts = await ethers.getSigners();

for (const account of accounts) {
console.log(account.address);
}
});

// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more

/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "0.7.3",
solidity: "0.8.0",
defaultNetwork: "hardhat",
networks: {
hardhat: {
Expand Down
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
{
"name": "drip-finance",
"scripts": {
"test": "npx hardhat test",
"compile": "npx hardhat compile"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"chai": "^4.3.4",
"ethereum-waffle": "^3.3.0",
"ethers": "^5.1.4",
"hardhat": "^2.2.1"
},
"dependencies": {
"@uniswap/v2-periphery": "^1.1.0-beta.0"
}
}
32 changes: 0 additions & 32 deletions scripts/sample-script.js

This file was deleted.

40 changes: 40 additions & 0 deletions test/DCAManagerTests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const { expect } = require("chai");

//TODO complete
describe("DCAManager functions", function() {

before(async function() {
const [user, relayer] = await ethers.getSigners();
this.user = user;
this.relayer = relayer;
const erc20 = await ethers.getContractFactory("ERC20");
const DCAManager = await ethers.getContractFactory("DCAManager");
//TODO get or deploy uniswap
this.baseToken = await erc20.deploy("BASE", 18);
this.destinationToken = await erc20.deploy("DEST", 18);
this.DCAManager = await DCAManager.deploy("0x0000000000000000000000000000000000000000");
const defaultSwapOrder = {
baseToken: this.baseToken.address,
amountBaseToken: 100000000000,
destinationToken: this.destinationToken.address,
fromTime: 0,
toTime: 100000000000000000000
};
this.order = defaultSwapOrder;
//TODO make sure to pad
const msg = `${defaultSwapOrder.baseToken}${defaultSwapOrder.amountBaseToken}${defaultSwapOrder.destinationToken}${defaultSwapOrder.fromTime}${defaultSwapOrder.toTime}`
const flatSignature = await user.signMessage(msg);
this.sig = ethers.utils.splitSignature(flatSignature);
});

it("Should fail to swap due to lack of approval from user", async function() {
expect(await this.DCAManager.swapOnUsersBehalf(...this.order, ...this.sig)).reverted;
});

it("Should be able to swap on behalf of the user", async function() {
const token = this.baseToken.connect(this.user);
token.approve(this.DCAManager.address, "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
const DCAManager = this.DCAManager.connect(this.relayer);
expect(await DCAManager.swapOnUsersBehalf(...this.order, ...this.sig)).to.equal(true, "swap executed");
});
});
14 changes: 0 additions & 14 deletions test/sample-test.js

This file was deleted.

0 comments on commit 21f7c32

Please sign in to comment.