Otacon - Research & Development
  • Welcome
  • Overview
  • Cybersecurity
    • Landscape
    • Attacks
    • Damage
    • Defenses
    • Outlook
  • Bounty
    • Programs
    • Manual
    • Assisted by Computers
    • Assisted by Humans
  • Otacon
    • Overview
    • Bug Scanning
    • Bug-to-Token Conversion
    • Proof of Concept
    • Submission
    • Revenue Share
    • Revenue Modifiers
  • Future
    • Scanning Accuracy
    • Scanning Agency
    • Roadmap
  • More
    • Tokenomics
      • OTACON Utility
      • OTACON Supply
      • OTACON Allocation
      • OTACON Fees
      • OTACON Burn
    • Smart Contracts
    • Liquidity Management
    • Team
  • Otacon [version 1.0]
    • Bug Bounty Management
    • Beta Test Plan
    • Bug Bounty Simulations
Powered by GitBook
On this page
  • 1. Contract Initialization
  • 2. Modifiers
  • 3. Collectible Management Functions
  • 4. Validator Management Functions
  • 5. Bounty Management Functions
  • 6. Staking Functions
  • 7. Validation and Reward Functions
  • 8. Administrative Functions
  • 9. ERC165 and Receiver Functions
  • 10. Fallback Functions
  1. Otacon [version 1.0]

Bug Bounty Management

The OtaconBountyRegistry smart contract manages bug bounties, staking of collectibles, and distribution of rewards in the Otacon ecosystem. This documentation provides a comprehensive breakdown of all contract functions, including explanations, TypeScript examples (using ethers.js), and simulations to showcase their usage.


1. Contract Initialization

The contract is initialized with important parameters and sets up immutable variables.

constructor() Ownable(msg.sender) ReentrancyGuard() {
    otaconToken = IERC20(0xFooBar);
    swapRouter = ISwapRouter(0xFooBar);
    WETH9 = 0xFooBar;
    transferOwnership(msg.sender);
}
  • Parameters:

    • otaconToken: The Otacon ERC20 token.

    • swapRouter: Uniswap V3 router for token swaps.

    • WETH9: Wrapped ETH token address.

  • Ownership: The deployer becomes the contract owner.


2. Modifiers

  • onlyBountyOwner(uint256 bountyId): Restricts function access to the owner of the bounty.


3. Collectible Management Functions

a. setProofCollectibleContract

Description: Sets the contract address for the ProofCollectible.

function setProofCollectibleContract(address tokenAddress) external onlyOwner
  • Parameters:

    • tokenAddress: Address of the ProofCollectible contract.

TypeScript Example:

// Assuming ethers.js is set up with provider and signer (owner)
const otaconRegistry = new ethers.Contract(registryAddress, registryABI, signer);

// Set the ProofCollectible contract address
async function setProofCollectibleContract(tokenAddress: string) {
  const tx = await otaconRegistry.setProofCollectibleContract(tokenAddress);
  await tx.wait();
  console.log('ProofCollectible contract address set.');
}

Simulation:

  • Owner calls setProofCollectibleContract with the ProofCollectible contract address.

  • The contract updates the proofCollectible state variable.

b. setSnippetCollectibleContract

Description: Sets the contract address for the SnippetCollectible (ERC721).

function setSnippetCollectibleContract(address tokenAddress) external onlyOwner

TypeScript Example:

async function setSnippetCollectibleContract(tokenAddress: string) {
  const tx = await otaconRegistry.setSnippetCollectibleContract(tokenAddress);
  await tx.wait();
  console.log('SnippetCollectible contract address set.');
}

Simulation:

  • Owner calls setSnippetCollectibleContract with the SnippetCollectible contract address.

  • The contract updates the snippetCollectible state variable.

c. setBountyPassCollectibleContract

Description: Sets the contract address for the BountyPassCollectible (ERC1155).

function setBountyPassCollectibleContract(address tokenAddress) external onlyOwner

TypeScript Example:

async function setBountyPassCollectibleContract(tokenAddress: string) {
  const tx = await otaconRegistry.setBountyPassCollectibleContract(tokenAddress);
  await tx.wait();
  console.log('BountyPassCollectible contract address set.');
}

Simulation:

  • Owner calls setBountyPassCollectibleContract with the BountyPassCollectible contract address.

  • The contract updates the bountyPassCollectible state variable.

d. setMultiplierCollectible

Description: Sets the multiplier collectible information for a specific tier.

function setMultiplierCollectible(
    MultiplierTier tier,
    address tokenAddress,
    uint256 multiplierValue,
    uint256 collectibleType
) external onlyOwner
  • Parameters:

    • tier: Enum value representing the multiplier tier (S, A, B, C, D, F).

    • tokenAddress: Address of the MultiplierCollectible contract.

    • multiplierValue: The value of the multiplier (e.g., 2e18 for 2x).

    • collectibleType: Token ID representing the tier in the ERC1155 contract.

TypeScript Example:

async function setMultiplierCollectible(
  tier: number, // Corresponding to the MultiplierTier enum
  tokenAddress: string,
  multiplierValue: ethers.BigNumber,
  collectibleType: number
) {
  const tx = await otaconRegistry.setMultiplierCollectible(
    tier,
    tokenAddress,
    multiplierValue,
    collectibleType
  );
  await tx.wait();
  console.log(`Multiplier collectible for tier ${tier} set.`);
}

Simulation:

  • Owner sets up multiplier collectibles for each tier with appropriate values.

  • The contract stores these configurations for use in staking and reward calculations.


4. Validator Management Functions

a. addValidator

Description: Adds a validator to a bounty.

function addValidator(uint256 bountyId, address validator) public
  • Access Control: Can be called by the bounty owner or the contract owner.

TypeScript Example:

async function addValidator(bountyId: number, validatorAddress: string) {
  const tx = await otaconRegistry.addValidator(bountyId, validatorAddress);
  await tx.wait();
  console.log(`Validator ${validatorAddress} added to bounty ${bountyId}.`);
}

Simulation:

  • Bounty Owner or Contract Owner adds a validator to a specific bounty.

  • The validator is added to the validators mapping and validatorList array.

b. removeValidator

Description: Removes a validator from a bounty.

function removeValidator(uint256 bountyId, address validator) public

TypeScript Example:

async function removeValidator(bountyId: number, validatorAddress: string) {
  const tx = await otaconRegistry.removeValidator(bountyId, validatorAddress);
  await tx.wait();
  console.log(`Validator ${validatorAddress} removed from bounty ${bountyId}.`);
}

Simulation:

  • Bounty Owner or Contract Owner removes a validator from a specific bounty.

  • The validator is removed from the validators mapping and validatorList array.


5. Bounty Management Functions

a. startBounty

Description: Starts a new bounty program with specified parameters and handles the creation fee.

function startBounty(
    BountyCreationParams calldata params,
    bool useOtaconToken,
    bool useETH,
    uint256 bountyPassTokenId
) external payable nonReentrant
  • Parameters:

    • params: Struct containing bounty details.

      • targetContract: Address of the contract under scrutiny.

      • rewards: Array of rewards per severity level.

      • rewardToken: ERC20 token used for rewards.

      • requireSnippet: Whether a code snippet is required.

      • targetNetwork: Network identifier.

      • targetEnvironment: Environment identifier.

      • validators: Initial list of validators.

    • useOtaconToken: Whether to pay the fee with Otacon tokens.

    • useETH: Whether to pay the fee with ETH.

    • bountyPassTokenId: Token ID of the Bounty Pass collectible (if not using Otacon or ETH).

TypeScript Example:

async function startBounty(
  params: {
    targetContract: string;
    rewards: ethers.BigNumber[];
    rewardToken: string;
    requireSnippet: boolean;
    targetNetwork: string;
    targetEnvironment: string;
    validators: string[];
  },
  useOtaconToken: boolean,
  useETH: boolean,
  bountyPassTokenId: number
) {
  let tx;
  if (useOtaconToken) {
    // Approve Otacon tokens
    const otaconToken = new ethers.Contract(otaconTokenAddress, erc20ABI, signer);
    await otaconToken.approve(registryAddress, otaconFee);
    tx = await otaconRegistry.startBounty(params, useOtaconToken, useETH, bountyPassTokenId);
  } else if (useETH) {
    tx = await otaconRegistry.startBounty(params, useOtaconToken, useETH, bountyPassTokenId, {
      value: ethFee,
    });
  } else {
    // Ensure you have the Bounty Pass collectible
    tx = await otaconRegistry.startBounty(params, useOtaconToken, useETH, bountyPassTokenId);
  }
  await tx.wait();
  console.log('Bounty started.');
}

Simulation:

  1. Scenario 1: Using Otacon Token

    • User approves otaconFee amount of Otacon tokens to the contract.

    • Calls startBounty with useOtaconToken = true.

    • The contract deducts the otaconFee from the user's balance.

    • Bounty is created and stored in the contract.

  2. Scenario 2: Using ETH

    • User sends a transaction with value = ethFee.

    • Calls startBounty with useETH = true.

    • The contract uses half of the ETH for an Otacon token buyback via Uniswap V3.

    • Bounty is created and stored in the contract.

  3. Scenario 3: Using Bounty Pass Collectible

    • User must own a Bounty Pass collectible.

    • Calls startBounty with bountyPassTokenId of the collectible they own.

    • The contract transfers and burns the Bounty Pass collectible.

    • Bounty is created and stored in the contract.

b. stopBounty

Description: Stops an active bounty.

function stopBounty(uint256 bountyId) external onlyBountyOwner(bountyId)

TypeScript Example:

async function stopBounty(bountyId: number) {
  const tx = await otaconRegistry.stopBounty(bountyId);
  await tx.wait();
  console.log(`Bounty ${bountyId} stopped.`);
}

Simulation:

  • Bounty Owner calls stopBounty.

  • The bounty's isActive state is set to false.

c. setBountyReward

Description: Sets the reward for a specific severity level in a bounty.

function setBountyReward(uint256 bountyId, uint8 severity, uint256 reward) external onlyBountyOwner(bountyId)

TypeScript Example:

async function setBountyReward(bountyId: number, severity: number, reward: ethers.BigNumber) {
  const tx = await otaconRegistry.setBountyReward(bountyId, severity, reward);
  await tx.wait();
  console.log(`Reward for severity ${severity} set to ${reward.toString()} tokens.`);
}

Simulation:

  • Bounty Owner updates the reward amounts for specific severity levels.

d. setProtocolFeePercentage

Description: Sets the protocol fee percentage.

function setProtocolFeePercentage(uint8 _protocolFeePercentage) external onlyOwner

TypeScript Example:

async function setProtocolFeePercentage(percentage: number) {
  const tx = await otaconRegistry.setProtocolFeePercentage(percentage);
  await tx.wait();
  console.log(`Protocol fee percentage set to ${percentage}%.`);
}

Simulation:

  • Contract Owner adjusts the protocol fee percentage used in reward calculations.


6. Staking Functions

a. stakeProofCollectible

Description: Stake a ProofCollectible (ERC721) to a bounty.

function stakeProofCollectible(uint256 bountyId, uint256 collectibleId) external nonReentrant

TypeScript Example:

async function stakeProofCollectible(bountyId: number, collectibleId: number) {
  // Approve the transfer of the ProofCollectible to the registry
  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}.`);
}

Simulation:

  • User approves the ProofCollectible for transfer.

  • Calls stakeProofCollectible with the bounty ID and collectible ID.

  • The contract transfers the ProofCollectible from the user to itself.

  • Records the staked collectible in stakedProofs.

b. unstakeProofCollectible

Description: Unstake a ProofCollectible from a bounty.

function unstakeProofCollectible(uint256 bountyId, uint256 collectibleId) external nonReentrant

TypeScript Example:

async function unstakeProofCollectible(bountyId: number, collectibleId: number) {
  const tx = await otaconRegistry.unstakeProofCollectible(bountyId, collectibleId);
  await tx.wait();
  console.log(`ProofCollectible ${collectibleId} unstaked from bounty ${bountyId}.`);
}

Simulation:

  • User calls unstakeProofCollectible.

  • The contract transfers the ProofCollectible back to the user.

  • Removes the collectible from stakedProofs.

c. stakeSnippetCollectible

Description: Stake a SnippetCollectible (ERC721) to a bounty.

function stakeSnippetCollectible(uint256 bountyId, uint256 collectibleId) external nonReentrant

TypeScript Example:

async function stakeSnippetCollectible(bountyId: number, collectibleId: number) {
  // Approve the transfer of the SnippetCollectible to the registry
  const snippetCollectible = new ethers.Contract(snippetCollectibleAddress, erc721ABI, signer);
  await snippetCollectible.approve(registryAddress, collectibleId);

  const tx = await otaconRegistry.stakeSnippetCollectible(bountyId, collectibleId);
  await tx.wait();
  console.log(`SnippetCollectible ${collectibleId} staked to bounty ${bountyId}.`);
}

Simulation:

  • User approves and stakes a SnippetCollectible to the bounty.

  • The contract records the staked snippet in stakedSnippets.

d. unstakeSnippetCollectible

Description: Unstake a SnippetCollectible from a bounty.

function unstakeSnippetCollectible(uint256 bountyId, uint256 collectibleId) external nonReentrant

TypeScript Example:

async function unstakeSnippetCollectible(bountyId: number, collectibleId: number) {
  const tx = await otaconRegistry.unstakeSnippetCollectible(bountyId, collectibleId);
  await tx.wait();
  console.log(`SnippetCollectible ${collectibleId} unstaked from bounty ${bountyId}.`);
}

Simulation:

  • User calls unstakeSnippetCollectible.

  • The contract transfers the SnippetCollectible back to the user.

  • Removes the collectible from stakedSnippets.

e. stakeMultiplierCollectible

Description: Stake a MultiplierCollectible (ERC1155) to a bounty.

function stakeMultiplierCollectible(
    uint256 bountyId,
    MultiplierTier multiplierTier,
    uint256 amount
) external nonReentrant

TypeScript Example:

async function stakeMultiplierCollectible(bountyId: number, tier: number, amount: number) {
  // Approve the transfer of the MultiplierCollectible to the registry
  const multiplierCollectible = new ethers.Contract(multiplierCollectibleAddress, erc1155ABI, signer);
  await multiplierCollectible.setApprovalForAll(registryAddress, true);

  const tx = await otaconRegistry.stakeMultiplierCollectible(bountyId, tier, amount);
  await tx.wait();
  console.log(`Staked ${amount} multiplier(s) of tier ${tier} to bounty ${bountyId}.`);
}

Simulation:

  • User approves the MultiplierCollectible for transfer.

  • Calls stakeMultiplierCollectible with the bounty ID, tier, and amount.

  • The contract transfers the specified amount of multiplier collectibles from the user to itself.

  • Records the staked multipliers in stakedMultipliers.

f. unstakeMultiplierCollectible

Description: Unstake MultiplierCollectibles from a bounty.

function unstakeMultiplierCollectible(uint256 bountyId, uint256 amount) external nonReentrant

TypeScript Example:

async function unstakeMultiplierCollectible(bountyId: number, amount: number) {
  const tx = await otaconRegistry.unstakeMultiplierCollectible(bountyId, amount);
  await tx.wait();
  console.log(`Unstaked ${amount} multiplier(s) from bounty ${bountyId}.`);
}

Simulation:

  • User calls unstakeMultiplierCollectible.

  • The contract transfers the specified amount of multiplier collectibles back to the user.

  • Updates the stakedMultipliers and totalMultiplierValueStaked.


7. Validation and Reward Functions

a. validateProof

Description: Validates a proof collectible, rewarding the bounty hunter and accumulating protocol fees.

function validateProof(uint256 bountyId, uint256 proofCollectibleId, uint8 severity) external nonReentrant

TypeScript Example:

async function validateProof(bountyId: number, proofCollectibleId: number, severity: number) {
  const tx = await otaconRegistry.validateProof(bountyId, proofCollectibleId, severity);
  await tx.wait();
  console.log(`ProofCollectible ${proofCollectibleId} validated for bounty ${bountyId}.`);
}

Simulation:

  • Validator calls validateProof.

  • The contract checks that the validator is authorized and the proof is staked.

  • Calculates the reward amounts:

    • Total Reward: From bounty.rewards[severity].

    • Protocol Fee: rewardAmount * protocolFeePercentage / 100.

    • Hunter Reward: rewardAmount - protocolFee.

  • Transfers the hunter reward to the bounty hunter.

  • Updates totalProtocolBountyReward and totalUnclaimedProtocolRewards.

  • Burns the proof collectible.

b. claimBountyShare

Description: Allows a staker to claim their share of the protocol bounty rewards.

function claimBountyShare(uint256 bountyId) external nonReentrant

TypeScript Example:

async function claimBountyShare(bountyId: number) {
  const tx = await otaconRegistry.claimBountyShare(bountyId);
  await tx.wait();
  console.log(`Bounty share claimed for bounty ${bountyId}.`);
}

Simulation:

  • User must have staked a proof and a multiplier.

  • Calls claimBountyShare.

  • The contract calculates the user's share based on their staked multiplier.

  • Applies a maximum cap (cannot exceed half of the total protocol bounty reward).

  • Burns the staked multiplier collectibles.

  • Transfers the calculated share to the user.

c. claimProtocolBountyShare

Description: Allows the protocol owner to claim its share of the protocol bounty rewards.

function claimProtocolBountyShare(uint256 bountyId) external onlyOwner nonReentrant

TypeScript Example:

async function claimProtocolBountyShare(bountyId: number) {
  const tx = await otaconRegistry.claimProtocolBountyShare(bountyId);
  await tx.wait();
  console.log(`Protocol bounty share claimed for bounty ${bountyId}.`);
}

Simulation:

  • Contract Owner calls claimProtocolBountyShare.

  • The contract calculates the remaining protocol share (cannot exceed half of the total protocol bounty reward).

  • Transfers the protocol share to the owner.


8. Administrative Functions

a. setFee

Description: Sets the Otacon or ETH fee for bounty creation.

function setFee(string calldata feeType, uint256 fee) external onlyOwner
  • Parameters:

    • feeType: Either "Otacon" or "ETH".

    • fee: The new fee amount.

TypeScript Example:

async function setFee(feeType: string, fee: ethers.BigNumber) {
  const tx = await otaconRegistry.setFee(feeType, fee);
  await tx.wait();
  console.log(`${feeType} fee set to ${fee.toString()}.`);
}

Simulation:

  • Contract Owner adjusts the fee amounts for bounty creation.

b. claimRevenue

Description: Withdraws accumulated bounty creation fees (Otacon tokens and ETH) to the owner.

function claimRevenue() external onlyOwner

TypeScript Example:

async function claimRevenue() {
  const tx = await otaconRegistry.claimRevenue();
  await tx.wait();
  console.log('Revenue claimed.');
}

Simulation:

  • Contract Owner calls claimRevenue.

  • The contract transfers all Otacon tokens and ETH held as fees to the owner.

c. getBounty

Description: Returns all bounty information for a given bounty ID.

function getBounty(uint256 bountyId) external view returns (...)

TypeScript Example:

async function getBounty(bountyId: number) {
  const bounty = await otaconRegistry.getBounty(bountyId);
  console.log('Bounty Details:', bounty);
}

Simulation:

  • User calls getBounty to retrieve bounty details.


9. ERC165 and Receiver Functions

  • supportsInterface: Indicates support for ERC1155Receiver and ERC721Receiver interfaces.

ERC1155Receiver Functions

  • onERC1155Received: Handles receipt of single ERC1155 token type.

  • onERC1155BatchReceived: Handles receipt of multiple ERC1155 token types.

ERC721Receiver Function

  • onERC721Received: Handles receipt of ERC721 tokens.

Note: These functions are called automatically during token transfers to the contract and do not require manual interaction in TypeScript.


10. Fallback Functions

  • receive: Allows the contract to receive ETH.

  • fallback: Fallback function to handle unexpected calls.

PreviousTeamNextBeta Test Plan

Last updated 7 months ago