Skip to content

Instantly share code, notes, and snippets.

@TripleSpeeder
Created November 15, 2021 11:09
Show Gist options
  • Save TripleSpeeder/18f429de3c84f94a02c60ef139018e09 to your computer and use it in GitHub Desktop.
Save TripleSpeeder/18f429de3c84f94a02c60ef139018e09 to your computer and use it in GitHub Desktop.
Hardhat script to start univ3 staker incentive
// 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