helpers.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. const hre = require("hardhat")
  2. const { expect } = require("chai")
  3. const { utils } = require("ethers")
  4. const { BigNumber } = require("ethers")
  5. // for testing permit()
  6. const PERMIT_TYPEHASH = utils.keccak256(utils.toUtf8Bytes("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"))
  7. print = (a) => {
  8. if (process.env.VERBOSE === undefined || process.env.VERBOSE === "true") console.log(a)
  9. }
  10. getAddr = async (ethers) => {
  11. const [owner, proxyOwner, bob, alice, user3, user4, badUser1, badUser2, fakeContract] = await ethers.getSigners()
  12. bob.name = "bob"
  13. alice.name = "alice"
  14. return {
  15. owner,
  16. proxyOwner,
  17. bob,
  18. alice,
  19. user3,
  20. user4,
  21. badUser1,
  22. badUser2,
  23. fakeContract,
  24. }
  25. }
  26. checkBalance = async (address, expected) => {
  27. let balance = await hre.ethers.provider.getBalance(address)
  28. expect(balance).to.equal(BigNumber.from(expected))
  29. return balance
  30. }
  31. checkTokenBalance = async (token, address, expected) => {
  32. const balance = await token.balanceOf(address)
  33. expect(balance).to.equal(BigNumber.from(expected))
  34. return balance
  35. }
  36. amountSDtoLD = (amount, poolObj) => {
  37. return BigNumber.from(amount.mul(String(10 ** (poolObj.ld - poolObj.sd))).toString())
  38. }
  39. amountLDtoSD = (amount, poolObj) => {
  40. return BigNumber.from(Math.floor(amount.div(String(10 ** (poolObj.ld - poolObj.sd)))).toString())
  41. }
  42. getRoundingDust = (amount, poolObj) => {
  43. return amount.sub(amountSDtoLD(amountLDtoSD(amount, poolObj), poolObj))
  44. }
  45. getBalance = async (address) => {
  46. return await hre.ethers.provider.getBalance(address)
  47. }
  48. getCurrentBlock = async () => {
  49. return (await hre.ethers.provider.getBlock("latest")).number
  50. }
  51. mineNBlocks = async (n) => {
  52. for (let index = 0; index < n; index++) {
  53. await ethers.provider.send("evm_mine")
  54. }
  55. }
  56. getFeeLibraryFromPool = async (pool) => {
  57. const feeLibraryAddr = await pool.feeLibrary()
  58. const FeeLibrary = await ethers.getContractFactory("StargateFeeLibraryV02")
  59. return await FeeLibrary.attach(feeLibraryAddr)
  60. }
  61. getPoolFromFactory = async (factory, poolId) => {
  62. const poolAddr = await factory.getPool(poolId)
  63. const Pool = await ethers.getContractFactory("Pool")
  64. return await Pool.attach(poolAddr)
  65. }
  66. getFeesFromFeeLibraryForPool = async (srcPoolObj, dstPoolObj, user, srcAmountSD) => {
  67. const feeLibrary = await getFeeLibraryFromPool(srcPoolObj.pool)
  68. return await feeLibrary.getFees(srcPoolObj.id, dstPoolObj.id, dstPoolObj.chainId, user.address, srcAmountSD)
  69. }
  70. getDefaultLzTxParams = (lzTxParams) => {
  71. lzTxParams.dstGasForCall = lzTxParams.dstGasForCall || 0
  72. lzTxParams.dstNativeAmount = lzTxParams.dstNativeAmount || 0
  73. lzTxParams.dstNativeAddr = lzTxParams.dstNativeAddr || "0x"
  74. return lzTxParams
  75. }
  76. getDomainSeparator = (name, tokenAddress) => {
  77. return utils.keccak256(
  78. utils.defaultAbiCoder.encode(
  79. ["bytes32", "bytes32", "bytes32", "uint256", "address"],
  80. [
  81. utils.keccak256(utils.toUtf8Bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")),
  82. utils.keccak256(utils.toUtf8Bytes(name)),
  83. utils.keccak256(utils.toUtf8Bytes("1")),
  84. 31337,
  85. tokenAddress,
  86. ]
  87. )
  88. )
  89. }
  90. getApprovalDigest = async (token, approve, nonce, deadline) => {
  91. const name = await token.name()
  92. const DOMAIN_SEPARATOR = getDomainSeparator(name, token.address)
  93. return utils.keccak256(
  94. utils.solidityPack(
  95. ["bytes1", "bytes1", "bytes32", "bytes32"],
  96. [
  97. "0x19",
  98. "0x01",
  99. DOMAIN_SEPARATOR,
  100. utils.keccak256(
  101. utils.defaultAbiCoder.encode(
  102. ["bytes32", "address", "address", "uint256", "uint256", "uint256"],
  103. [PERMIT_TYPEHASH, approve.owner, approve.spender, approve.value, nonce, deadline]
  104. )
  105. ),
  106. ]
  107. )
  108. )
  109. }
  110. deployNew = async (contractName, params = []) => {
  111. const C = await ethers.getContractFactory(contractName)
  112. return await C.deploy(...params)
  113. }
  114. encodeParams = (types, values, packed = false) => {
  115. if (!packed) {
  116. return web3.eth.abi.encodeParameters(types, values)
  117. } else {
  118. return ethers.utils.solidityPack(types, values)
  119. }
  120. }
  121. encodePackedParams = (types, values) => {
  122. return encodeParams(types, values, true)
  123. }
  124. decodeParam = (type, value) => {
  125. return web3.eth.abi.decodeParameter(type, value)
  126. }
  127. // !!! Use at own risk, txEther might need to be increased if running out of gas
  128. callAsContract = async (contract, impersonateAddr, funcNameAsStr, params = [], msgValue = 0) => {
  129. const existingBal = await hre.ethers.provider.getBalance(impersonateAddr)
  130. // Might need to increase this for big transactions
  131. const txEther = BigNumber.from("10000000000000000000000000")
  132. const msgValueBn = BigNumber.from(msgValue)
  133. // Update the balance on the network
  134. await network.provider.send("hardhat_setBalance", [
  135. impersonateAddr,
  136. existingBal.add(txEther).add(msgValueBn).toHexString().replace("0x0", "0x"),
  137. ])
  138. // Retrieve the signer for the person to impersonate
  139. const signer = await ethers.getSigner(impersonateAddr)
  140. // Impersonate the smart contract to make the corresponding call on their behalf
  141. await hre.network.provider.request({
  142. method: "hardhat_impersonateAccount",
  143. params: [impersonateAddr],
  144. })
  145. // Process the transaction on their behalf
  146. const rec = await contract.connect(signer)[funcNameAsStr](...params, { value: msgValueBn })
  147. const tx = await rec.wait()
  148. // The amount of gas consumed by the transaction
  149. const etherUsedForGas = tx.gasUsed.mul(tx.effectiveGasPrice)
  150. const extraEther = txEther.sub(etherUsedForGas)
  151. // Balance post transaction
  152. const currentBal = await hre.ethers.provider.getBalance(impersonateAddr)
  153. // Subtract the difference in the amount of ether given
  154. // vs the amount used in the transaction
  155. await hre.network.provider.send("hardhat_setBalance", [impersonateAddr, currentBal.sub(extraEther).toHexString().replace("0x0", "0x")])
  156. // Undo the impersonate so we go back to the default
  157. await hre.network.provider.request({
  158. method: "hardhat_stopImpersonatingAccount",
  159. params: [impersonateAddr],
  160. })
  161. return rec
  162. }
  163. module.exports = {
  164. getAddr,
  165. callAsContract,
  166. checkBalance,
  167. checkTokenBalance,
  168. getBalance,
  169. deployNew,
  170. encodePackedParams,
  171. encodeParams,
  172. decodeParam,
  173. amountSDtoLD,
  174. amountLDtoSD,
  175. getFeeLibraryFromPool,
  176. getFeesFromFeeLibraryForPool,
  177. getPoolFromFactory,
  178. getDefaultLzTxParams,
  179. getRoundingDust,
  180. getCurrentBlock,
  181. mineNBlocks,
  182. getApprovalDigest,
  183. }