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

feat(smart-contarcts): add support for swap and purchase when a discount hook is activated #13456

Closed
wants to merge 13 commits into from
30 changes: 27 additions & 3 deletions packages/contracts/src/abis/utils/UnlockSwapPurchaser.json

Large diffs are not rendered by default.

2,121 changes: 1,850 additions & 271 deletions packages/contracts/src/contracts/utils/UnlockSwapPurchaser.sol

Large diffs are not rendered by default.

7 changes: 1 addition & 6 deletions packages/contracts/src/index.ts
Expand Up @@ -77,9 +77,4 @@ export { UnlockDiscountTokenV2 }
export { UnlockDiscountTokenV3 }
export { GovernorUnlockProtocol }
export { GovernorUnlockProtocolTimelock }
export {
LockSerializer,
UnlockSwapPurchaser,
UnlockSwapBurner,
UniswapOracleV3,
}
export { LockSerializer,UnlockSwapPurchaser,UnlockSwapBurner,UniswapOracleV3 }
6 changes: 3 additions & 3 deletions packages/hardhat-helpers/package.json
Expand Up @@ -20,14 +20,14 @@
"@nomiclabs/hardhat-ethers": "2.2.3",
"@nomiclabs/hardhat-waffle": "2.0.6",
"@uniswap/permit2-sdk": "1.2.0",
"@uniswap/sdk-core": "4.0.9",
"@uniswap/smart-order-router": "3.19.2",
"@uniswap/v3-sdk": "3.10.2",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed as this was not used. This seems to help remove errors!

"@uniswap/sdk-core": "4.2.0",
"@uniswap/smart-order-router": "3.25.0",
"@unlock-protocol/contracts": "workspace:^",
"@unlock-protocol/networks": "workspace:^",
"@unlock-protocol/tsconfig": "workspace:^",
"@unlock-protocol/types": "workspace:^",
"ethers": "6.10.0",
"ethersv5": "npm:ethers@^5.7.2",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added because the alphe router needs it!

"hardhat": "2.20.1",
"typescript": "5.3.3",
"zksync-ethers": "6.1.0"
Expand Down
26 changes: 15 additions & 11 deletions packages/hardhat-helpers/src/fork.js
Expand Up @@ -27,7 +27,7 @@ async function getWhales(chainId = 1) {
case 1:
return {
[tokens.DAI]: '0x075e72a5eDf65F0A5f44699c7654C1a76941Ddc8', // PulseX
[tokens.USDC]: '0x8EB8a3b98659Cce290402893d0123abb75E3ab28',
[tokens.USDC]: '0xD6153F5af5679a75cC85D8974463545181f48772',
[tokens.WBTC]: '0x845cbCb8230197F733b59cFE1795F282786f212C',
[tokens.UDT]: '0xF5C28ce24Acf47849988f147d5C75787c0103534', // unlock-protocol.eth
}
Expand Down Expand Up @@ -61,11 +61,11 @@ const parseForkUrl = (networks) => {
name: `${name} (forked locally)`,
accounts: process.env.DEPLOYER_PRIVATE_KEY
? [
{
privateKey: process.env.DEPLOYER_PRIVATE_KEY,
balance: '10000000000000000000000', // 1000 ETH yah
},
]
{
privateKey: process.env.DEPLOYER_PRIVATE_KEY,
balance: '10000000000000000000000', // 1000 ETH yah
},
]
: undefined,
}

Expand Down Expand Up @@ -94,10 +94,7 @@ const resetNodeState = async () => {
})
}

const addSomeETH = async (
address,
amount = ethers.utils.parseEther('1000')
) => {
const addSomeETH = async (address, amount = ethers.parseEther('1000')) => {
const { network } = require('hardhat')
const balance = `0x${BigInt(amount.toString()).toString(16)}`
await network.provider.send('hardhat_setBalance', [address, balance])
Expand Down Expand Up @@ -160,13 +157,20 @@ const addERC20 = async function (
}

// otherwise use transfer from whales
const erc20Contract = await ethers.getContractAt(ERC20_ABI, tokenAddress)
const whales = await getWhales()
if (!whales[tokenAddress])
throw Error(`No whale for this address: ${tokenAddress}`)

const whaleBalance = await erc20Contract.balanceOf(whales[tokenAddress])
if (whaleBalance.lt(amount)) {
throw Error(
`Whale at address: ${whales[tokenAddress]} does not have enough ${tokenAddress} to transfer ${amount} to ${address} (only has ${whaleBalance})`
)
}
const whale = await ethers.getSigner(whales[tokenAddress])
await impersonate(whale.address)

const erc20Contract = await ethers.getContractAt(ERC20_ABI, tokenAddress)
await erc20Contract.connect(whale).transfer(address, amount)
return erc20Contract
}
Expand Down
19 changes: 12 additions & 7 deletions packages/hardhat-helpers/src/uniswap.js
@@ -1,4 +1,5 @@
const { ethers } = require('ethers')
const { ethers: ethersv5 } = require('ethersv5')

const { AllowanceTransfer } = require('@uniswap/permit2-sdk')
const {
Expand Down Expand Up @@ -26,11 +27,11 @@ const PERMIT2_ADDRESS = '0x000000000022D473030F116dDEE9F6B43aC78BA3'
// convert swap jsbi to ethers BigNumber
const currencyAmountToBigNumber = (amount) => {
const { decimals } = amount.currency
const fixed = ethers.FixedNumber.from(amount.toExact())
const tokenScale = ethers.FixedNumber.from(
ethers.BigNumber.from(10).pow(decimals)
const fixed = ethersv5.FixedNumber.from(amount.toExact())
const tokenScale = ethersv5.FixedNumber.from(
ethersv5.BigNumber.from(10).pow(decimals)
)
return ethers.BigNumber.from(
return ethersv5.BigNumber.from(
// have to remove trailing .0 "manually" :/
fixed.mulUnsafe(tokenScale).floor().toString().split('.')[0]
)
Expand All @@ -47,18 +48,22 @@ async function getUniswapRoute({
slippageTolerance = new Percent(10, 100),
deadline = Math.floor(new Date().getTime() / 1000 + 100000),
permitOptions: { usePermit2Sig = false, inputTokenPermit } = {},
chainId,
chainId = 1,
}) {
// init router

const provider = new ethersv5.providers.JsonRpcProvider(
`https://rpc.unlock-protocol.com/${chainId}`
)
const router = new AlphaRouter({
chainId,
provider: ethers.provider,
provider,
})

// parse router args
const outputAmount = CurrencyAmount.fromRawAmount(
tokenOut,
JSBI.BigInt(amoutOut)
amoutOut //JSBI.BigInt(amoutOut)
)
const routeArgs = [
outputAmount,
Expand Down
1 change: 1 addition & 0 deletions packages/networks/src/networks/sepolia.ts
Expand Up @@ -84,6 +84,7 @@ export const sepolia: NetworkConfig = {
networkName: 'sepolia',
studioName: 'unlock-protocol-sepolia',
},
swapPurchaser: '0x580A4a5a9612371e3832c4559026B9Ee3b23Cc11',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deplpyed on Sepolia but can't test because we're getting 404 on

failed to resolve /ipns/api.uniswap.org/v1/pools/v3/sepolia.json: no link named "sepolia.json" under QmaimGCW33MN3uCAZYQmckXLCFQCgt82bypYt4tWqpiU32

tokens: [
{
address: '0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9',
Expand Down