Created
November 15, 2021 11:09
-
-
Save TripleSpeeder/18f429de3c84f94a02c60ef139018e09 to your computer and use it in GitHub Desktop.
Hardhat script to start univ3 staker incentive
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// We require the Hardhat Runtime Environment explicitly here. This is optional | |
// but useful for running the script in a standalone fashion through `node <script>`. | |
// | |
// When running the script with `hardhat run <script>` you'll find the Hardhat | |
// Runtime Environment's members available in the global scope. | |
import { ethers, network, getNamedAccounts } from "hardhat"; | |
import v3StakerABI from "../abi/uniswap-v3-staker.json"; | |
import { UniswapV3Staker } from "../typechain/UniswapV3Staker"; | |
import { BasicToken } from "../typechain"; | |
async function main() { | |
// Hardhat always runs the compile task when running scripts with its command | |
// line interface. | |
// | |
// If this script is run directly using `node` you may want to call compile | |
// manually to make sure everything is compiled | |
// await run('compile'); | |
if (network.name === "hardhat") { | |
console.warn( | |
"You are running with Hardhat network, which" + | |
" gets automatically created and destroyed every time. Use the Hardhat" + | |
" option '--network <localhost|Rinkeby|MainNet|xDai>" | |
); | |
} | |
if (network.name !== "rinkeby") { | |
console.warn(`For now this script only supports rinkeby network`); | |
return; | |
} | |
const { deployer } = await getNamedAccounts(); | |
let stakerAddress, rewardsTokenAddress, poolAddress, refundee; | |
// rinkeby addresses: | |
stakerAddress = "0x1f98407aaB862CdDeF78Ed252D6f557aA5b0f00d"; | |
poolAddress = YOUR_POOL_ADDRESS; | |
rewardsTokenAddress = YOUR REWARDS_TOKEN_ADDRESS; | |
refundee = deployer; | |
const uniswapV3Staker = (await ethers.getContractAt( | |
v3StakerABI, | |
stakerAddress | |
)) as UniswapV3Staker; | |
const rewardsToken = (await ethers.getContractAt( | |
"BasicToken", | |
rewardsTokenAddress | |
)) as BasicToken; | |
// times are in seconds. Program shall run 1 year, starting 10 minutes after deployment | |
const startTime = Math.floor(Date.now() / 1000) + 60 * 10; | |
const endTime = startTime + 60 * 60 * 24 * 360; | |
// 5000000 total reward | |
const reward = ethers.utils.parseUnits("5000000", 18); | |
// calculate incentiveId | |
const types = ["address", "address", "uint256", "uint256", "address"]; | |
const values = [ | |
rewardsTokenAddress, | |
poolAddress, | |
startTime, | |
endTime, | |
refundee, | |
]; | |
const encodedKey = ethers.utils.defaultAbiCoder.encode(types, values); | |
const incentiveId = ethers.utils.keccak256(encodedKey); | |
console.log(`The new incentiveId will be ${incentiveId}`); | |
// check balance of acting account | |
console.log( | |
`Checking if deployer (${deployer}) has enough rewards token balance...` | |
); | |
const deployerBalance = await rewardsToken.balanceOf(deployer); | |
const missingBalance = reward.sub(deployerBalance); | |
if (missingBalance.gt(0)) { | |
console.warn( | |
`deployer (${deployer}) does not have enough balance to transfer reward!` | |
); | |
console.warn( | |
`reward amount: ${ethers.utils.formatEther( | |
reward | |
)} (${reward.toString()})` | |
); | |
console.warn( | |
`current balance: ${ethers.utils.formatEther( | |
deployerBalance | |
)} (${deployerBalance.toString()})` | |
); | |
console.warn( | |
`missing amount: ${ethers.utils.formatEther( | |
missingBalance | |
)} (${missingBalance.toString()})` | |
); | |
return; | |
} else { | |
console.log( | |
`Balance ${ethers.utils.formatEther( | |
deployerBalance | |
)} (${deployerBalance.toString()}) is sufficient.` | |
); | |
} | |
// set up allowance for reward amount | |
console.log( | |
`Checking if deployer (${deployer}) has approved staker contract to spend the reward...` | |
); | |
const existingAllowance = await rewardsToken.allowance( | |
deployer, | |
uniswapV3Staker.address | |
); | |
const missingAllowance = reward.sub(existingAllowance); | |
if (missingAllowance.gt(0)) { | |
console.log( | |
`Missing ${missingAllowance.toString()} allowance. Setting up allowance...` | |
); | |
const allowanceTx = await rewardsToken.approve( | |
uniswapV3Staker.address, | |
reward | |
); | |
console.log(`Creating approve() tx ${allowanceTx.hash}...`); | |
await allowanceTx.wait(); | |
console.log(`Tx ${allowanceTx.hash} confirmed!`); | |
} else { | |
console.log( | |
`Allowance ${ethers.utils.formatEther( | |
existingAllowance | |
)} (${existingAllowance.toString()}) is sufficient.` | |
); | |
} | |
const tx = await uniswapV3Staker.createIncentive( | |
{ | |
startTime, | |
endTime, | |
pool: poolAddress, | |
rewardToken: rewardsTokenAddress, | |
refundee, | |
}, | |
reward, | |
{ | |
gasLimit: 100000, // similar tx on rinkeby cost ~88500, see https://rinkeby.etherscan.io/tx/0x76812c3bf5b187b3b1618289a71ad00df3bc32a2d615aa752eda67a71a77784a | |
} | |
); | |
console.log(`Creating incentive in tx ${tx.hash}...`); | |
await tx.wait(); | |
console.log(`Tx ${tx.hash} confirmed!`); | |
} | |
// We recommend this pattern to be able to use async/await everywhere | |
// and properly handle errors. | |
main() | |
.then(() => process.exit(0)) | |
.catch((error) => { | |
console.error(error); | |
process.exit(1); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment