Initial commit with 🏗️ create-eth @ 2.0.4
This commit is contained in:
2
packages/hardhat/test/.gitkeep
Normal file
2
packages/hardhat/test/.gitkeep
Normal file
@@ -0,0 +1,2 @@
|
||||
# Write tests for your smart contract in this directory
|
||||
# Example: YourContract.ts
|
||||
165
packages/hardhat/test/RiggedRoll.ts
Normal file
165
packages/hardhat/test/RiggedRoll.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
import hre from "hardhat";
|
||||
import { expect } from "chai";
|
||||
// import { parseEther } from "ethers";
|
||||
import { DiceGame, RiggedRoll, RiggedRoll__factory } from "../typechain-types";
|
||||
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
|
||||
|
||||
const { ethers } = hre;
|
||||
|
||||
describe("🚩 Challenge: 🎲 Dice Game", function () {
|
||||
let diceGame: DiceGame;
|
||||
let riggedRoll: RiggedRoll;
|
||||
let deployer: HardhatEthersSigner;
|
||||
const { provider } = ethers;
|
||||
|
||||
const rollAmountString = "0.002";
|
||||
const rollAmount = ethers.parseEther(rollAmountString);
|
||||
|
||||
async function deployContracts() {
|
||||
[deployer] = await ethers.getSigners();
|
||||
const DiceGame = await ethers.getContractFactory("DiceGame");
|
||||
diceGame = await DiceGame.deploy();
|
||||
|
||||
const contractAddress = process.env.CONTRACT_ADDRESS;
|
||||
let contractArtifact;
|
||||
if (contractAddress) {
|
||||
contractArtifact = `contracts/download-${contractAddress}.sol:RiggedRoll`;
|
||||
} else {
|
||||
contractArtifact = "contracts/RiggedRoll.sol:RiggedRoll";
|
||||
}
|
||||
|
||||
const diceGameAddress = await diceGame.getAddress();
|
||||
const RiggedRoll = (await ethers.getContractFactory(contractArtifact)) as RiggedRoll__factory;
|
||||
riggedRoll = await RiggedRoll.deploy(diceGameAddress);
|
||||
}
|
||||
|
||||
async function fundRiggedContract() {
|
||||
const riggedRollAddress = await riggedRoll.getAddress();
|
||||
return deployer.sendTransaction({
|
||||
to: riggedRollAddress,
|
||||
value: rollAmount,
|
||||
});
|
||||
}
|
||||
|
||||
async function getRoll(getRollLessThanFive: boolean) {
|
||||
let expectedRoll;
|
||||
while (true) {
|
||||
const latestBlockNumber = await provider.getBlockNumber();
|
||||
const block = await provider.getBlock(latestBlockNumber);
|
||||
if (!block) {
|
||||
return;
|
||||
}
|
||||
const prevHash = block.hash;
|
||||
const nonce = await diceGame.nonce();
|
||||
|
||||
const diceGameAddress = await diceGame.getAddress();
|
||||
const hash = ethers.solidityPackedKeccak256(
|
||||
["bytes32", "address", "uint256"],
|
||||
[prevHash, diceGameAddress, nonce],
|
||||
);
|
||||
|
||||
const bigInt = BigInt(hash);
|
||||
expectedRoll = bigInt % 16n;
|
||||
if (expectedRoll < 5n == getRollLessThanFive) {
|
||||
break;
|
||||
}
|
||||
|
||||
const options = { value: rollAmount };
|
||||
await diceGame.rollTheDice(options);
|
||||
}
|
||||
return expectedRoll;
|
||||
}
|
||||
|
||||
describe("Checkpoint2: 🔑 Rigged Contract", function () {
|
||||
beforeEach(async function () {
|
||||
await deployContracts();
|
||||
});
|
||||
|
||||
it("Checkpoint2: Should deploy contracts", async function () {
|
||||
const diceGameAddress = await diceGame.getAddress();
|
||||
expect(await riggedRoll.diceGame()).to.equal(diceGameAddress);
|
||||
});
|
||||
|
||||
it(`Checkpoint2: Should revert if balance is less than ${rollAmountString} ethers`, async function () {
|
||||
await expect(riggedRoll.riggedRoll())
|
||||
.to.be.revertedWithCustomError(riggedRoll, "NotEnoughETH")
|
||||
.withArgs(rollAmount, 0);
|
||||
});
|
||||
|
||||
it("Checkpoint2: Should transfer sufficient eth to RiggedRoll", async function () {
|
||||
console.log("\t", "💸 Funding RiggedRoll contract");
|
||||
await fundRiggedContract();
|
||||
const riggedRollAddress = await riggedRoll.getAddress();
|
||||
const balance = await provider.getBalance(riggedRollAddress);
|
||||
console.log("\t", "💲 RiggedRoll balance: ", ethers.formatEther(balance));
|
||||
expect(balance).to.gte(rollAmount, `Error when expecting DiceGame contract to have >= ${rollAmount} eth`);
|
||||
});
|
||||
|
||||
it("Checkpoint2: Should call diceGame.rollTheDice for a roll <= 5", async () => {
|
||||
console.log("\t", "💸 Funding RiggedRoll contract");
|
||||
await fundRiggedContract();
|
||||
|
||||
const getRollLessThanFive = true;
|
||||
const expectedRoll = await getRoll(getRollLessThanFive);
|
||||
console.log("\t", "🎲 Expect roll to be less than or equal to 5. Dice Game Roll:", Number(expectedRoll));
|
||||
|
||||
const tx = await riggedRoll.riggedRoll();
|
||||
const riggedRollAddress = await riggedRoll.getAddress();
|
||||
|
||||
await expect(tx).to.emit(diceGame, "Roll").withArgs(riggedRollAddress, rollAmount, expectedRoll);
|
||||
await expect(tx).to.emit(diceGame, "Winner");
|
||||
});
|
||||
|
||||
it("Checkpoint2: Should not call diceGame.rollTheDice for a roll > 5", async () => {
|
||||
console.log("\t", "💸 Funding RiggedRoll contract");
|
||||
await fundRiggedContract();
|
||||
|
||||
const getRollLessThanFive = false;
|
||||
const expectedRoll = await getRoll(getRollLessThanFive);
|
||||
console.log("\t", "🎲 Expect roll to be greater than 5. Dice Game Roll:", Number(expectedRoll));
|
||||
console.log("\t", "◀ Expect riggedRoll to be reverted");
|
||||
|
||||
await expect(riggedRoll.riggedRoll())
|
||||
.to.be.revertedWithCustomError(riggedRoll, "NotWinningRoll")
|
||||
.withArgs(expectedRoll);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Checkpoint3: 💵 Where's my money?!?", function () {
|
||||
beforeEach(async function () {
|
||||
await deployContracts();
|
||||
});
|
||||
|
||||
it("Checkpoint3: Should withdraw funds", async () => {
|
||||
console.log("\t", "💸 Funding RiggedRoll contract");
|
||||
await fundRiggedContract();
|
||||
|
||||
const deployerPrevBalance = await provider.getBalance(deployer.address);
|
||||
console.log("\t", "💲 Current RiggedRoll balance: ", ethers.formatEther(deployerPrevBalance));
|
||||
const riggedRollAddress = await riggedRoll.getAddress();
|
||||
const riggedRollBalance = await provider.getBalance(riggedRollAddress);
|
||||
await riggedRoll.withdraw(deployer.address, riggedRollBalance);
|
||||
|
||||
const deployerCurrentBalance = await provider.getBalance(deployer.address);
|
||||
console.log("\t", "💲 New RiggedRoll balance: ", ethers.formatEther(deployerCurrentBalance));
|
||||
|
||||
expect(
|
||||
deployerPrevBalance < deployerCurrentBalance,
|
||||
"Error when expecting RiggedRoll balance to increase when calling withdraw",
|
||||
).to.true;
|
||||
});
|
||||
|
||||
it("Checkpoint3: Should revert withdraw when amount exceeds contract balance", async () => {
|
||||
console.log("\t", "💸 Funding RiggedRoll contract");
|
||||
await fundRiggedContract();
|
||||
|
||||
const riggedRollAddress = await riggedRoll.getAddress();
|
||||
const riggedRollBalance = await provider.getBalance(riggedRollAddress);
|
||||
const tooMuch = riggedRollBalance + rollAmount;
|
||||
|
||||
await expect(riggedRoll.withdraw(deployer.address, tooMuch))
|
||||
.to.be.revertedWithCustomError(riggedRoll, "InsufficientBalance")
|
||||
.withArgs(tooMuch, riggedRollBalance);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user