Fix error codes

This commit is contained in:
Karl Kempe 2022-06-02 15:53:12 +00:00
parent bc16d7d509
commit a5945de3a7
5 changed files with 65 additions and 78 deletions

View File

@ -1,10 +1,13 @@
use anchor_lang::prelude::*;
#[error_code]
pub enum SaleError {
pub enum ContributorError {
#[msg("AmountTooLarge")]
AmountTooLarge,
#[msg("BuyerInactive")]
BuyerInactive,
#[msg("ContributionTooEarly")]
ContributionTooEarly,
@ -56,12 +59,3 @@ pub enum SaleError {
#[msg("TooManyAcceptedTokens")]
TooManyAcceptedTokens,
}
#[error_code]
pub enum BuyerError {
#[msg("BuyerInactive")]
BuyerInactive,
#[msg("InvalidTokenIndex")]
InvalidTokenIndex,
}

View File

@ -251,13 +251,13 @@ pub mod anchor_contributor {
pub fn claim_refund(ctx: Context<ClaimRefund>) -> Result<()> {
let sale = &mut ctx.accounts.sale;
require!(sale.is_aborted(), SaleError::SaleNotAborted);
require!(sale.is_aborted(), ContributorError::SaleNotAborted);
let refunds = ctx.accounts.buyer.claim_refunds(&sale.totals)?;
let atas = &ctx.remaining_accounts;
require!(
atas.len() == 2 * sale.totals.len(),
SaleError::InvalidRemainingAccounts
ContributorError::InvalidRemainingAccounts
);
let owner = &ctx.accounts.owner.key();
@ -272,10 +272,13 @@ pub mod anchor_contributor {
let mint = token::accessor::mint(&buyer_ata)?;
require!(
sale.get_token_index(&mint).is_ok(),
SaleError::InvalidRemainingAccounts
ContributorError::InvalidRemainingAccounts
);
let authority = token::accessor::authority(&buyer_ata)?;
require!(authority == *owner, SaleError::InvalidRemainingAccounts);
require!(
authority == *owner,
ContributorError::InvalidRemainingAccounts
);
}
let custodian_index = buyer_index + 1;
@ -284,10 +287,13 @@ pub mod anchor_contributor {
let mint = token::accessor::mint(&custodian_ata)?;
require!(
sale.get_token_index(&mint).is_ok(),
SaleError::InvalidRemainingAccounts
ContributorError::InvalidRemainingAccounts
);
let authority = token::accessor::authority(&custodian_ata)?;
require!(authority == *custodian, SaleError::InvalidRemainingAccounts);
require!(
authority == *custodian,
ContributorError::InvalidRemainingAccounts
);
}
// TODO: transfer back to owner

View File

@ -1,7 +1,7 @@
use anchor_lang::prelude::*;
use num_derive::*;
use crate::{constants::ACCEPTED_TOKENS_MAX, error::BuyerError, state::sale::AssetTotal};
use crate::{constants::ACCEPTED_TOKENS_MAX, error::ContributorError, state::sale::AssetTotal};
#[account]
pub struct Buyer {
@ -30,8 +30,11 @@ impl Buyer {
}
pub fn contribute(&mut self, idx: usize, amount: u64) -> Result<()> {
require!(self.is_active(), BuyerError::BuyerInactive);
require!(idx < ACCEPTED_TOKENS_MAX, BuyerError::InvalidTokenIndex);
require!(self.is_active(), ContributorError::BuyerInactive);
require!(
idx < ACCEPTED_TOKENS_MAX,
ContributorError::InvalidTokenIndex
);
self.contributed[idx] += amount;
Ok(())
}
@ -40,7 +43,7 @@ impl Buyer {
// total allocations and excess contributions for each
// token index
pub fn claim_allocations(&mut self, totals: &Vec<AssetTotal>) -> Result<Vec<BuyerTotal>> {
require!(self.is_active(), BuyerError::BuyerInactive);
require!(self.is_active(), ContributorError::BuyerInactive);
let mut buyer_totals: Vec<BuyerTotal> = Vec::with_capacity(totals.len());
for (i, asset) in totals.iter().enumerate() {
@ -64,7 +67,7 @@ impl Buyer {
}
pub fn claim_refunds(&mut self, totals: &Vec<AssetTotal>) -> Result<Vec<BuyerTotal>> {
require!(self.is_active(), BuyerError::BuyerInactive);
require!(self.is_active(), ContributorError::BuyerInactive);
let mut refunds: Vec<BuyerTotal> = Vec::with_capacity(totals.len());
for (i, asset) in totals.iter().enumerate() {

View File

@ -7,7 +7,7 @@ use std::{str::FromStr, u64};
use crate::{
constants::*,
env::*,
error::SaleError,
error::ContributorError,
wormhole::{get_message_data, MessageData},
};
@ -68,7 +68,7 @@ impl AssetTotal {
pub fn make_from_slice(bytes: &[u8]) -> Result<Self> {
require!(
bytes.len() == INDEX_ACCEPTED_TOKEN_END,
SaleError::InvalidAcceptedTokenPayload
ContributorError::InvalidAcceptedTokenPayload
);
Ok(AssetTotal {
token_index: bytes[INDEX_ACCEPTED_TOKEN_INDEX],
@ -99,20 +99,20 @@ impl Sale {
}
pub fn parse_sale_init(&mut self, payload: &[u8]) -> Result<()> {
require!(!self.initialized, SaleError::SaleAlreadyInitialized);
require!(!self.initialized, ContributorError::SaleAlreadyInitialized);
self.initialized = true;
// check that the payload has at least the number of bytes
// required to define the number of accepted tokens
require!(
payload.len() > INDEX_SALE_INIT_ACCEPTED_TOKENS_START,
SaleError::IncorrectVaaPayload
ContributorError::IncorrectVaaPayload
);
let num_accepted = payload[INDEX_SALE_INIT_ACCEPTED_TOKENS_START] as usize;
require!(
num_accepted <= ACCEPTED_TOKENS_MAX,
SaleError::TooManyAcceptedTokens
ContributorError::TooManyAcceptedTokens
);
self.totals = Vec::with_capacity(ACCEPTED_TOKENS_MAX);
@ -150,7 +150,7 @@ impl Sale {
pub fn set_native_sale_token_decimals(&mut self, decimals: u8) -> Result<()> {
require!(
self.token_decimals >= decimals,
SaleError::InvalidTokenDecimals
ContributorError::InvalidTokenDecimals
);
self.native_token_decimals = decimals;
Ok(())
@ -158,7 +158,7 @@ impl Sale {
pub fn get_token_index(&self, mint: &Pubkey) -> Result<u8> {
let result = self.totals.iter().find(|item| item.mint == *mint);
require!(result != None, SaleError::InvalidTokenIndex);
require!(result != None, ContributorError::InvalidTokenIndex);
Ok(result.unwrap().token_index)
}
@ -177,12 +177,12 @@ impl Sale {
token_index: u8,
contributed: u64,
) -> Result<usize> {
require!(self.is_active(block_time), SaleError::SaleEnded);
require!(self.is_active(block_time), ContributorError::SaleEnded);
let block_time = block_time as u64;
require!(
block_time >= self.times.start,
SaleError::ContributionTooEarly
ContributorError::ContributionTooEarly
);
let idx = self.get_index(token_index)?;
self.totals[idx].contributions += contributed;
@ -191,7 +191,10 @@ impl Sale {
}
pub fn serialize_contributions(&self, block_time: i64) -> Result<Vec<u8>> {
require!(self.is_attestable(block_time), SaleError::SaleNotAttestable);
require!(
self.is_attestable(block_time),
ContributorError::SaleNotAttestable
);
let totals = &self.totals;
let mut attested: Vec<u8> = Vec::with_capacity(
@ -211,19 +214,19 @@ impl Sale {
}
pub fn parse_sale_sealed(&mut self, payload: &[u8]) -> Result<()> {
require!(!self.has_ended(), SaleError::SaleEnded);
require!(!self.has_ended(), ContributorError::SaleEnded);
// check that the payload has at least the number of bytes
// required to define the number of allocations
require!(
payload.len() > INDEX_SALE_SEALED_ALLOCATIONS_START,
SaleError::IncorrectVaaPayload
ContributorError::IncorrectVaaPayload
);
let totals = &mut self.totals;
let num_allocations = payload[INDEX_SALE_SEALED_ALLOCATIONS_START] as usize;
require!(
num_allocations == totals.len(),
SaleError::IncorrectVaaPayload
ContributorError::IncorrectVaaPayload
);
let grand_total_allocations: u64 = 0;
@ -242,7 +245,7 @@ impl Sale {
let adjusted = allocation / BigUint::from(10u128).pow(decimal_difference);
require!(
adjusted < BigUint::from(u64::MAX),
SaleError::AmountTooLarge
ContributorError::AmountTooLarge
);
// is there a better way to do this part?
@ -254,7 +257,7 @@ impl Sale {
);
require!(
excess_contributions > BigUint::from(0 as u128),
SaleError::AmountTooLarge
ContributorError::AmountTooLarge
);
let total = &mut totals[i];
@ -273,13 +276,13 @@ impl Sale {
}
pub fn parse_sale_aborted(&mut self, payload: &[u8]) -> Result<()> {
require!(!self.has_ended(), SaleError::SaleEnded);
require!(!self.has_ended(), ContributorError::SaleEnded);
// check that the payload has the correct size
// payload type + sale id
require!(
payload.len() == PAYLOAD_HEADER_LEN,
SaleError::IncorrectVaaPayload
ContributorError::IncorrectVaaPayload
);
// finally set the status to aborted
@ -313,7 +316,7 @@ impl Sale {
.totals
.iter()
.position(|item| item.token_index == token_index);
require!(result != None, SaleError::InvalidTokenIndex);
require!(result != None, ContributorError::InvalidTokenIndex);
Ok(result.unwrap())
}
@ -343,17 +346,20 @@ pub fn verify_conductor_vaa<'info>(
require!(
vaa_account.to_account_info().owner == &Pubkey::from_str(CORE_BRIDGE_ADDRESS).unwrap(),
SaleError::InvalidVaaAction
ContributorError::InvalidVaaAction
);
require!(
msg.emitter_chain == get_conductor_chain()?,
SaleError::InvalidConductor
ContributorError::InvalidConductor
);
require!(
msg.emitter_address == get_conductor_address()?,
SaleError::InvalidConductor
ContributorError::InvalidConductor
);
require!(
msg.payload[0] == payload_type,
ContributorError::InvalidVaaAction
);
require!(msg.payload[0] == payload_type, SaleError::InvalidVaaAction);
Ok(msg)
}

View File

@ -67,7 +67,7 @@ describe("anchor-contributor", () => {
const tokenAccount = await getOrCreateAssociatedTokenAccount(connection, buyer, mint, buyer.publicKey);
// now mint to buyer for testing
let amount = new BN("20000000000");
let amount = new BN("200000000000");
await mintTo(
connection,
orchestrator,
@ -193,7 +193,7 @@ describe("anchor-contributor", () => {
let caughtError = false;
try {
const tx = await contributor.initSale(orchestrator, dummyConductor.initSaleVaa);
console.log("should not happen", tx);
throw Error(`should not happen: ${tx}`);
} catch (e) {
// pda init should fail
caughtError = "programErrorStack" in e;
@ -212,7 +212,7 @@ describe("anchor-contributor", () => {
try {
const mint = hexToPublicKey(dummyConductor.acceptedTokens[0].address);
const tx = await contributor.contribute(buyer, saleId, mint, new BN(amount));
console.log("should not happen", tx);
throw Error(`should not happen: ${tx}`);
} catch (e) {
caughtError = verifyErrorMsg(e, "ContributionTooEarly");
}
@ -328,7 +328,7 @@ describe("anchor-contributor", () => {
let caughtError = false;
try {
const tx = await contributor.attestContributions(orchestrator, saleId);
console.log("should not happen", tx);
throw Error(`should not happen: ${tx}`);
} catch (e) {
caughtError = verifyErrorMsg(e, "SaleNotAttestable");
}
@ -354,23 +354,6 @@ describe("anchor-contributor", () => {
//expect(caughtError).to.be.false;
});
// TODO
it("Orchestrator Cannot Attest Contributions Again", async () => {
const saleId = dummyConductor.getSaleId();
let caughtError = false;
try {
const tx = await contributor.attestContributions(orchestrator, saleId);
console.log("should not happen", tx);
} catch (e) {
caughtError = verifyErrorMsg(e, "SaleNotAttestable");
}
if (!caughtError) {
throw Error("did not catch expected error");
}
});
it("User Cannot Contribute After Sale Ended", async () => {
const saleId = dummyConductor.getSaleId();
const amount = new BN("1000000000"); // 1,000,000,000 lamports
@ -379,7 +362,7 @@ describe("anchor-contributor", () => {
try {
const mint = hexToPublicKey(dummyConductor.acceptedTokens[0].address);
const tx = await contributor.contribute(buyer, saleId, mint, amount);
console.log("should not happen", tx);
throw Error(`should not happen: ${tx}`);
} catch (e) {
caughtError = verifyErrorMsg(e, "SaleEnded");
}
@ -414,7 +397,7 @@ describe("anchor-contributor", () => {
let caughtError = false;
try {
const tx = await contributor.sealSale(orchestrator, saleSealedVaa);
console.log("should not happen", tx);
throw Error(`should not happen: ${tx}`);
} catch (e) {
caughtError = verifyErrorMsg(e, "SaleEnded");
}
@ -422,13 +405,6 @@ describe("anchor-contributor", () => {
if (!caughtError) {
throw Error("did not catch expected error");
}
expect(false).to.be.true;
});
// TODO
it("User Cannot Claim Allocations with Incorrect Token Index", async () => {
expect(false).to.be.true;
});
// TODO
@ -546,7 +522,7 @@ describe("anchor-contributor", () => {
let caughtError = false;
try {
const tx = await contributor.abortSale(orchestrator, saleAbortedVaa);
console.log("should not happen", tx);
throw Error(`should not happen: ${tx}`);
} catch (e) {
caughtError = verifyErrorMsg(e, "SaleEnded");
}
@ -563,7 +539,9 @@ describe("anchor-contributor", () => {
return hexToPublicKey(token.address);
});
//const tx = await contributor.claimRefund(buyer, saleId, acceptedMints);
const tx = await contributor.claimRefund(buyer, saleId, acceptedMints);
// get buyer state and verify inactive
});
// TODO
@ -575,8 +553,8 @@ describe("anchor-contributor", () => {
let caughtError = false;
try {
//const tx = await contributor.claimRefund(saleId, buyer, acceptedMints);
//console.log("should not happen", tx);
const tx = await contributor.claimRefund(buyer, saleId, acceptedMints);
throw Error(`should not happen: ${tx}`);
} catch (e) {
caughtError = verifyErrorMsg(e, "BuyerInactive");
}
@ -595,7 +573,7 @@ function verifyErrorMsg(e: any, msg: string): boolean {
console.error(e);
}
return result;
} else if (e.error.errorMessage) {
} else if (e.error) {
const result = e.error.errorMessage == msg;
if (!result) {
console.error(e);