Bug Bounty Simulations
Below are detailed simulations for the key functions, demonstrating their interactions and outcomes.
A. Creating a Bounty
Scenario 1: Using Otacon Tokens
User wants to create a bounty using Otacon tokens.
User approves
otaconFeeOtacon tokens for transfer to the registry contract.User calls
startBountywithuseOtaconToken = true.
TypeScript Example:
async function createBountyWithOtacon() {
const otaconToken = new ethers.Contract(otaconTokenAddress, erc20ABI, signer);
await otaconToken.approve(registryAddress, otaconFee);
const bountyParams = {
targetContract: '0xTargetContractAddress',
rewards: [1000, 2000, 3000, 4000].map(ethers.utils.parseUnits),
rewardToken: '0xRewardTokenAddress',
requireSnippet: true,
targetNetwork: ethers.utils.formatBytes32String('Ethereum'),
targetEnvironment: ethers.utils.formatBytes32String('Mainnet'),
validators: [],
};
const tx = await otaconRegistry.startBounty(bountyParams, true, false, 0);
await tx.wait();
console.log('Bounty created using Otacon tokens.');
}Outcome:
Otacon tokens are transferred from the user to the contract.
Bounty is created and assigned a new
bountyId.
Scenario 2: Using ETH
User sends
ethFeeamount of ETH with the transaction.User calls
startBountywithuseETH = true.
TypeScript Example:
async function createBountyWithETH() {
const bountyParams = {
// Same as above
};
const tx = await otaconRegistry.startBounty(bountyParams, false, true, 0, {
value: ethFee,
});
await tx.wait();
console.log('Bounty created using ETH.');
}Outcome:
Half of the ETH is used to buy back Otacon tokens via Uniswap V3.
Bounty is created and assigned a new
bountyId.
Scenario 3: Using Bounty Pass Collectible
User owns a Bounty Pass collectible (
bountyPassTokenId).User calls
startBountywithbountyPassTokenId.
TypeScript Example:
async function createBountyWithBountyPass(bountyPassTokenId: number) {
const bountyParams = {
// Same as above
};
// Approve Bounty Pass transfer
const bountyPassCollectible = new ethers.Contract(bountyPassCollectibleAddress, erc1155ABI, signer);
await bountyPassCollectible.setApprovalForAll(registryAddress, true);
const tx = await otaconRegistry.startBounty(bountyParams, false, false, bountyPassTokenId);
await tx.wait();
console.log('Bounty created using Bounty Pass.');
}Outcome:
Bounty Pass collectible is transferred to the contract and burned.
Bounty is created and assigned a new
bountyId.
B. Staking a Collectible
Staking a ProofCollectible
User owns a ProofCollectible (
collectibleId).User approves the transfer.
User calls
stakeProofCollectible.
TypeScript Example:
async function stakeProof() {
const collectibleId = 123;
const bountyId = 1;
const proofCollectible = new ethers.Contract(proofCollectibleAddress, erc721ABI, signer);
await proofCollectible.approve(registryAddress, collectibleId);
const tx = await otaconRegistry.stakeProofCollectible(bountyId, collectibleId);
await tx.wait();
console.log(`ProofCollectible ${collectibleId} staked to bounty ${bountyId}.`);
}Outcome:
The ProofCollectible is transferred to the contract.
Recorded in
stakedProofs.
C. Validating a Proof of Bug
Validator calls
validateProofwith thebountyId,proofCollectibleId, andseverity.The contract checks authorization and existence of the staked proof.
Calculates rewards and protocol fees.
Transfers rewards and updates state.
TypeScript Example:
async function validateProofOfBug() {
const bountyId = 1;
const proofCollectibleId = 123;
const severity = 2;
const tx = await otaconRegistry.validateProof(bountyId, proofCollectibleId, severity);
await tx.wait();
console.log(`ProofCollectible ${proofCollectibleId} validated for bounty ${bountyId}.`);
}Outcome:
Bounty hunter receives their reward.
Protocol fees are accumulated.
ProofCollectible is burned.
D. Distributing Rewards to a Bounty Hunter
Handled within
validateProof.The hunter's reward is transferred during validation.
Protocol fee is calculated and stored.
E. Claiming a Bounty Share
User must have staked a proof and a multiplier.
User calls
claimBountyShare.Contract calculates the user's share.
Burns the staked multiplier collectibles.
Transfers the share to the user.
TypeScript Example:
async function claimBountyShare() {
const bountyId = 1;
const tx = await otaconRegistry.claimBountyShare(bountyId);
await tx.wait();
console.log(`Bounty share claimed for bounty ${bountyId}.`);
}Outcome:
User receives their calculated share of the protocol bounty rewards.
Multiplier collectibles are burned.
User cannot claim again for the same bounty.
Last updated