New tests and fixes in Terra Wormhole contracts
- added new descriptive errors in terra wormhole contract - 0-expiration guardian sets error fixed - added script for test VAAs generation - added full test coverage for the VAA processing in the contract - fixed cargo clippy/fmt warnings
This commit is contained in:
parent
eaee9c0638
commit
701154457c
|
@ -0,0 +1,335 @@
|
|||
// vaa-test generates VAA test fixtures used by the ETH devnet tests
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"github.com/certusone/wormhole/bridge/pkg/vaa"
|
||||
)
|
||||
|
||||
type signerInfo struct {
|
||||
signer *ecdsa.PrivateKey
|
||||
index int
|
||||
}
|
||||
|
||||
var i = 0
|
||||
|
||||
var defaultTargetAddress = vaa.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
|
||||
|
||||
func main() {
|
||||
|
||||
keys := generateKeys(6)
|
||||
for i, key := range keys {
|
||||
fmt.Printf("Key [%d]: %s\n", i, crypto.PubkeyToAddress(key.PublicKey).String())
|
||||
}
|
||||
|
||||
// 0 - Valid transfer, single signer
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(2000, 0),
|
||||
Payload: &vaa.BodyTransfer{
|
||||
Nonce: 56,
|
||||
SourceChain: 1,
|
||||
TargetChain: 3,
|
||||
SourceAddress: vaa.Address{2, 1, 4},
|
||||
TargetAddress: defaultTargetAddress,
|
||||
Asset: &vaa.AssetMeta{
|
||||
Chain: vaa.ChainIDSolana,
|
||||
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
|
||||
Decimals: 8,
|
||||
},
|
||||
Amount: big.NewInt(1000000000000000000),
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}})
|
||||
|
||||
// 1 - 2 signers, invalid order
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(2000, 0),
|
||||
Payload: &vaa.BodyTransfer{
|
||||
Nonce: 56,
|
||||
SourceChain: 1,
|
||||
TargetChain: 3,
|
||||
SourceAddress: vaa.Address{2, 1, 4},
|
||||
TargetAddress: defaultTargetAddress,
|
||||
Asset: &vaa.AssetMeta{
|
||||
Chain: vaa.ChainIDEthereum,
|
||||
Address: hexToAddress("0xd833215cbcc3f914bd1c9ece3ee7bf8b14f841bb"),
|
||||
Decimals: 8,
|
||||
},
|
||||
Amount: big.NewInt(1000000000000000000),
|
||||
},
|
||||
}, []*signerInfo{{keys[1], 1}, {keys[0], 0}})
|
||||
|
||||
// 2 - Valid transfer, 2 signers
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(2000, 0),
|
||||
Payload: &vaa.BodyTransfer{
|
||||
Nonce: 56,
|
||||
SourceChain: 1,
|
||||
TargetChain: 3,
|
||||
SourceAddress: vaa.Address{2, 1, 4},
|
||||
TargetAddress: defaultTargetAddress,
|
||||
Asset: &vaa.AssetMeta{
|
||||
Chain: vaa.ChainIDEthereum,
|
||||
Address: hexToAddress("0xd833215cbcc3f914bd1c9ece3ee7bf8b14f841bb"),
|
||||
Decimals: 8,
|
||||
},
|
||||
Amount: big.NewInt(1000000000000000000),
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}, {keys[1], 1}})
|
||||
|
||||
// 3 - Valid transfer, 3 signers
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(2000, 0),
|
||||
Payload: &vaa.BodyTransfer{
|
||||
Nonce: 56,
|
||||
SourceChain: 1,
|
||||
TargetChain: 3,
|
||||
SourceAddress: vaa.Address{2, 1, 4},
|
||||
TargetAddress: defaultTargetAddress,
|
||||
Asset: &vaa.AssetMeta{
|
||||
Chain: vaa.ChainIDEthereum,
|
||||
Address: hexToAddress("0xd833215cbcc3f914bd1c9ece3ee7bf8b14f841bb"),
|
||||
Decimals: 8,
|
||||
},
|
||||
Amount: big.NewInt(1000000000000000000),
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}, {keys[1], 1}, {keys[2], 2}})
|
||||
|
||||
// 4 - Invalid signature, single signer
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(2000, 0),
|
||||
Payload: &vaa.BodyTransfer{
|
||||
Nonce: 56,
|
||||
SourceChain: 1,
|
||||
TargetChain: 3,
|
||||
SourceAddress: vaa.Address{2, 1, 4},
|
||||
TargetAddress: defaultTargetAddress,
|
||||
Asset: &vaa.AssetMeta{
|
||||
Chain: vaa.ChainIDSolana,
|
||||
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
|
||||
Decimals: 8,
|
||||
},
|
||||
Amount: big.NewInt(1000000000000000000),
|
||||
},
|
||||
}, []*signerInfo{{keys[1], 0}})
|
||||
|
||||
// 5 - Valid guardian set change
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(2000, 0),
|
||||
Payload: &vaa.BodyGuardianSetUpdate{
|
||||
Keys: []common.Address{
|
||||
crypto.PubkeyToAddress(keys[1].PublicKey),
|
||||
},
|
||||
NewIndex: 1,
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}})
|
||||
|
||||
// 6 - Change from set 0 to set 1, single guardian with key#2 (zero-based)
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(2000, 0),
|
||||
Payload: &vaa.BodyGuardianSetUpdate{
|
||||
Keys: []common.Address{
|
||||
crypto.PubkeyToAddress(keys[2].PublicKey),
|
||||
},
|
||||
NewIndex: 1,
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}})
|
||||
|
||||
// 7 - Guardian set index jump
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(2000, 0),
|
||||
Payload: &vaa.BodyGuardianSetUpdate{
|
||||
Keys: []common.Address{
|
||||
crypto.PubkeyToAddress(keys[2].PublicKey),
|
||||
},
|
||||
NewIndex: 2,
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}})
|
||||
|
||||
// 8 - Invalid target address format
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(2000, 0),
|
||||
Payload: &vaa.BodyTransfer{
|
||||
Nonce: 56,
|
||||
SourceChain: 1,
|
||||
TargetChain: 3,
|
||||
SourceAddress: vaa.Address{2, 1, 4},
|
||||
TargetAddress: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
|
||||
Asset: &vaa.AssetMeta{
|
||||
Chain: vaa.ChainIDSolana,
|
||||
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
|
||||
Decimals: 8,
|
||||
},
|
||||
Amount: big.NewInt(1000000000000000000),
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}})
|
||||
|
||||
// 9 - Amount too high (max u128 + 1)
|
||||
amount, ok := new(big.Int).SetString("100000000000000000000000000000000", 16)
|
||||
if !ok {
|
||||
panic("Cannot convert big amount")
|
||||
}
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(2000, 0),
|
||||
Payload: &vaa.BodyTransfer{
|
||||
Nonce: 56,
|
||||
SourceChain: 1,
|
||||
TargetChain: 3,
|
||||
SourceAddress: vaa.Address{2, 1, 4},
|
||||
TargetAddress: defaultTargetAddress,
|
||||
Asset: &vaa.AssetMeta{
|
||||
Chain: vaa.ChainIDSolana,
|
||||
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
|
||||
Decimals: 8,
|
||||
},
|
||||
Amount: amount,
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}})
|
||||
|
||||
// 10 - Same source and target
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(1000, 0),
|
||||
Payload: &vaa.BodyTransfer{
|
||||
Nonce: 56,
|
||||
SourceChain: 3,
|
||||
TargetChain: 3,
|
||||
SourceAddress: vaa.Address{2, 1, 4},
|
||||
TargetAddress: defaultTargetAddress,
|
||||
Asset: &vaa.AssetMeta{
|
||||
Chain: vaa.ChainIDSolana,
|
||||
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
|
||||
Decimals: 8,
|
||||
},
|
||||
Amount: big.NewInt(1000000000000000000),
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}})
|
||||
|
||||
// 11 - Wrong target chain
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(1000, 0),
|
||||
Payload: &vaa.BodyTransfer{
|
||||
Nonce: 56,
|
||||
SourceChain: 1,
|
||||
TargetChain: 2,
|
||||
SourceAddress: vaa.Address{2, 1, 4},
|
||||
TargetAddress: defaultTargetAddress,
|
||||
Asset: &vaa.AssetMeta{
|
||||
Chain: vaa.ChainIDSolana,
|
||||
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
|
||||
Decimals: 8,
|
||||
},
|
||||
Amount: big.NewInt(1000000000000000000),
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}})
|
||||
|
||||
// 12 - Change guardian set to 6 addresses
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 0,
|
||||
Timestamp: time.Unix(4000, 0),
|
||||
Payload: &vaa.BodyGuardianSetUpdate{
|
||||
Keys: []common.Address{
|
||||
crypto.PubkeyToAddress(keys[0].PublicKey),
|
||||
crypto.PubkeyToAddress(keys[1].PublicKey),
|
||||
crypto.PubkeyToAddress(keys[2].PublicKey),
|
||||
crypto.PubkeyToAddress(keys[3].PublicKey),
|
||||
crypto.PubkeyToAddress(keys[4].PublicKey),
|
||||
crypto.PubkeyToAddress(keys[5].PublicKey),
|
||||
},
|
||||
NewIndex: 1,
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}})
|
||||
|
||||
// 13 - Valid transfer, partial quorum
|
||||
signAndPrintVAA(&vaa.VAA{
|
||||
Version: 1,
|
||||
GuardianSetIndex: 1,
|
||||
Timestamp: time.Unix(4000, 0),
|
||||
Payload: &vaa.BodyTransfer{
|
||||
Nonce: 57,
|
||||
SourceChain: 1,
|
||||
TargetChain: 3,
|
||||
SourceAddress: vaa.Address{2, 1, 5},
|
||||
TargetAddress: defaultTargetAddress,
|
||||
Asset: &vaa.AssetMeta{
|
||||
Chain: vaa.ChainIDSolana,
|
||||
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
|
||||
Decimals: 8,
|
||||
},
|
||||
Amount: big.NewInt(1000000000000000000),
|
||||
},
|
||||
}, []*signerInfo{{keys[0], 0}, {keys[1], 1}, {keys[3], 3}, {keys[4], 4}, {keys[5], 5}})
|
||||
}
|
||||
|
||||
func signAndPrintVAA(vaa *vaa.VAA, signers []*signerInfo) {
|
||||
for _, signer := range signers {
|
||||
vaa.AddSignature(signer.signer, uint8(signer.index))
|
||||
}
|
||||
vData, err := vaa.Marshal()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
println(i, hex.EncodeToString(vData))
|
||||
i++
|
||||
}
|
||||
|
||||
func generateKeys(n int) (keys []*ecdsa.PrivateKey) {
|
||||
r := rand.New(rand.NewSource(555))
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
key, err := ecdsa.GenerateKey(crypto.S256(), r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func hexToAddress(hex string) vaa.Address {
|
||||
hexAddr := common.HexToAddress(hex)
|
||||
return padAddress(hexAddr)
|
||||
}
|
||||
|
||||
func padAddress(address common.Address) vaa.Address {
|
||||
paddedAddress := common.LeftPadBytes(address[:], 32)
|
||||
|
||||
addr := vaa.Address{}
|
||||
copy(addr[:], paddedAddress)
|
||||
|
||||
return addr
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -119,7 +119,7 @@ fn handle_mint_wrapped<S: Storage, A: Api, Q: Querier>(
|
|||
return Err(StdError::unauthorized());
|
||||
}
|
||||
|
||||
return Ok(handle_mint(deps, env, recipient, amount)?);
|
||||
Ok(handle_mint(deps, env, recipient, amount)?)
|
||||
}
|
||||
|
||||
pub fn query<S: Storage, A: Api, Q: Querier>(
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#![allow(clippy::field_reassign_with_default)]
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ thiserror = { version = "1.0.20" }
|
|||
k256 = { version = "0.5.9", default-features = false, features = ["ecdsa"] }
|
||||
sha3 = { version = "0.9.1", default-features = false }
|
||||
hex = "0.4.2"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
cosmwasm-vm = { version = "0.10.0", default-features = false, features = ["default-cranelift"] }
|
|
@ -18,8 +18,6 @@ use cw20_base::msg::QueryMsg as TokenQuery;
|
|||
|
||||
use cw20::TokenInfoResponse;
|
||||
|
||||
use hex;
|
||||
|
||||
use cw20_wrapped::msg::HandleMsg as WrappedMsg;
|
||||
use cw20_wrapped::msg::InitMsg as WrappedInit;
|
||||
use cw20_wrapped::msg::QueryMsg as WrappedQuery;
|
||||
|
@ -69,14 +67,24 @@ pub fn handle<S: Storage, A: Api, Q: Querier>(
|
|||
) -> StdResult<HandleResponse> {
|
||||
match msg {
|
||||
HandleMsg::SubmitVAA { vaa } => handle_submit_vaa(deps, env, &vaa.as_slice()),
|
||||
HandleMsg::RegisterAssetHook { asset_id } => handle_register_asset(deps, env, &asset_id.as_slice()),
|
||||
HandleMsg::RegisterAssetHook { asset_id } => {
|
||||
handle_register_asset(deps, env, &asset_id.as_slice())
|
||||
}
|
||||
HandleMsg::LockAssets {
|
||||
asset,
|
||||
recipient,
|
||||
amount,
|
||||
target_chain,
|
||||
nonce,
|
||||
} => handle_lock_assets(deps, env, asset, amount, recipient.as_slice(), target_chain, nonce),
|
||||
} => handle_lock_assets(
|
||||
deps,
|
||||
env,
|
||||
asset,
|
||||
amount,
|
||||
recipient.as_slice(),
|
||||
target_chain,
|
||||
nonce,
|
||||
),
|
||||
HandleMsg::SetActive { is_active } => handle_set_active(deps, env, is_active),
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +95,6 @@ fn handle_submit_vaa<S: Storage, A: Api, Q: Querier>(
|
|||
env: Env,
|
||||
data: &[u8],
|
||||
) -> StdResult<HandleResponse> {
|
||||
|
||||
let state = config_read(&deps.storage).load()?;
|
||||
if !state.is_active {
|
||||
return ContractError::ContractInactive.std_err();
|
||||
|
@ -132,13 +139,13 @@ fn handle_submit_vaa<S: Storage, A: Api, Q: Querier>(
|
|||
if vaa_archive_check(&deps.storage, &hash) {
|
||||
return ContractError::VaaAlreadyExecuted.std_err();
|
||||
}
|
||||
|
||||
|
||||
// Load and check guardian set
|
||||
let guardian_set = guardian_set_get(&deps.storage, vaa_guardian_set_index);
|
||||
let guardian_set: GuardianSetInfo =
|
||||
guardian_set.or(ContractError::InvalidGuardianSetIndex.std_err())?;
|
||||
guardian_set.or_else(|_| ContractError::InvalidGuardianSetIndex.std_err())?;
|
||||
|
||||
if guardian_set.expiration_time == 0 || guardian_set.expiration_time < env.block.time {
|
||||
if guardian_set.expiration_time != 0 && guardian_set.expiration_time < env.block.time {
|
||||
return ContractError::GuardianSetExpired.std_err();
|
||||
}
|
||||
if len_signers < guardian_set.quorum() {
|
||||
|
@ -151,21 +158,26 @@ fn handle_submit_vaa<S: Storage, A: Api, Q: Querier>(
|
|||
for _ in 0..len_signers {
|
||||
let index = data.get_u8(pos) as i32;
|
||||
if index <= last_index {
|
||||
return Err(ContractError::WrongGuardianIndexOrder.std());
|
||||
return ContractError::WrongGuardianIndexOrder.std_err();
|
||||
}
|
||||
last_index = index;
|
||||
|
||||
let signature = Signature::try_from(&data[pos + 1..pos + 1 + 64])
|
||||
.or(ContractError::CannotDecodeSignature.std_err())?;
|
||||
.or_else(|_| ContractError::CannotDecodeSignature.std_err())?;
|
||||
let id = RecoverableId::new(data.get_u8(pos + 1 + 64))
|
||||
.or(ContractError::CannotDecodeSignature.std_err())?;
|
||||
.or_else(|_| ContractError::CannotDecodeSignature.std_err())?;
|
||||
let recoverable_signature = RecoverableSignature::new(&signature, id)
|
||||
.or(ContractError::CannotDecodeSignature.std_err())?;
|
||||
.or_else(|_| ContractError::CannotDecodeSignature.std_err())?;
|
||||
|
||||
let verify_key = recoverable_signature
|
||||
.recover_verify_key_from_digest_bytes(&hash)
|
||||
.or(ContractError::CannotRecoverKey.std_err())?;
|
||||
if !keys_equal(&verify_key, &guardian_set.addresses[index as usize]) {
|
||||
.or_else(|_| ContractError::CannotRecoverKey.std_err())?;
|
||||
|
||||
let index = index as usize;
|
||||
if index >= guardian_set.addresses.len() {
|
||||
return ContractError::TooManySignatures.std_err();
|
||||
}
|
||||
if !keys_equal(&verify_key, &guardian_set.addresses[index]) {
|
||||
return ContractError::GuardianSignatureError.std_err();
|
||||
}
|
||||
pos += SIGNATURE_LEN;
|
||||
|
@ -204,7 +216,7 @@ fn handle_register_asset<S: Storage, A: Api, Q: Querier>(
|
|||
match result {
|
||||
Ok(_) => {
|
||||
// Asset already registered, return error
|
||||
return ContractError::AssetAlreadyRegistered.std_err();
|
||||
ContractError::AssetAlreadyRegistered.std_err()
|
||||
}
|
||||
Err(_) => {
|
||||
bucket.save(asset_id, &env.message.sender)?;
|
||||
|
@ -343,7 +355,10 @@ fn vaa_transfer<S: Storage, A: Api, Q: Querier>(
|
|||
messages.push(CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr,
|
||||
msg: to_binary(&WrappedMsg::Mint {
|
||||
recipient: deps.api.human_address(&target_address)?,
|
||||
recipient: deps
|
||||
.api
|
||||
.human_address(&target_address)
|
||||
.or_else(|_| ContractError::WrongTargetAddressFormat.std_err())?,
|
||||
amount: Uint128::from(amount),
|
||||
})?,
|
||||
send: vec![],
|
||||
|
@ -359,7 +374,10 @@ fn vaa_transfer<S: Storage, A: Api, Q: Querier>(
|
|||
asset_address: asset_address.to_vec().into(),
|
||||
decimals: data.get_u8(103),
|
||||
mint: Some(InitMint {
|
||||
recipient: deps.api.human_address(&target_address)?,
|
||||
recipient: deps
|
||||
.api
|
||||
.human_address(&target_address)
|
||||
.or_else(|_| ContractError::WrongTargetAddressFormat.std_err())?,
|
||||
amount: Uint128::from(amount),
|
||||
}),
|
||||
init_hook: Some(InitHook {
|
||||
|
@ -443,7 +461,7 @@ fn handle_lock_assets<S: Storage, A: Api, Q: Querier>(
|
|||
contract_addr: asset.clone(),
|
||||
msg: to_binary(&WrappedMsg::Burn {
|
||||
account: env.message.sender.clone(),
|
||||
amount: Uint128::from(amount),
|
||||
amount,
|
||||
})?,
|
||||
send: vec![],
|
||||
}));
|
||||
|
@ -459,11 +477,11 @@ fn handle_lock_assets<S: Storage, A: Api, Q: Querier>(
|
|||
Err(_) => {
|
||||
// This is a regular asset, transfer its balance
|
||||
messages.push(CosmosMsg::Wasm(WasmMsg::Execute {
|
||||
contract_addr: asset.clone(),
|
||||
contract_addr: asset,
|
||||
msg: to_binary(&TokenMsg::TransferFrom {
|
||||
owner: env.message.sender.clone(),
|
||||
recipient: env.contract.address.clone(),
|
||||
amount: Uint128::from(amount),
|
||||
amount,
|
||||
})?,
|
||||
send: vec![],
|
||||
}));
|
||||
|
@ -479,7 +497,12 @@ fn handle_lock_assets<S: Storage, A: Api, Q: Querier>(
|
|||
log("locked.token_chain", asset_chain),
|
||||
log("locked.token_decimals", decimals),
|
||||
log("locked.token", hex::encode(asset_address)),
|
||||
log("locked.sender", hex::encode(extend_address_to_32(&deps.api.canonical_address(&env.message.sender)?))),
|
||||
log(
|
||||
"locked.sender",
|
||||
hex::encode(extend_address_to_32(
|
||||
&deps.api.canonical_address(&env.message.sender)?,
|
||||
)),
|
||||
),
|
||||
log("locked.recipient", hex::encode(recipient)),
|
||||
log("locked.amount", amount),
|
||||
log("locked.nonce", nonce),
|
||||
|
@ -559,36 +582,77 @@ fn keys_equal(a: &VerifyKey, b: &GuardianAddress) -> bool {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::{UNIX_EPOCH, SystemTime};
|
||||
use super::*;
|
||||
use crate::state::GuardianSetInfo;
|
||||
use cosmwasm_std::testing::{mock_dependencies, mock_env};
|
||||
use cosmwasm_std::HumanAddr;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
// Constants generated by bridge/cmd/vaa-test-terra/main.go
|
||||
const ADDR_1: &str = "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe";
|
||||
const ADDR_2: &str = "8575Df9b3c97B4E267Deb92d93137844A97A0132";
|
||||
const VAA_VALID_TRANSFER: &str = "010000000001001063f503dd308134e0f158537f54c5799719f4fa2687dd276c72ef60ae0c82c47d4fb560545afaabdf60c15918e221763fd1892c75f2098c0ffd5db4af254a4501000007d01000000038010302010400000000000000000000000000000000000000000000000000000000000101010101010101010101010101010101010101000000000000000000000000010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000";
|
||||
const VAA_VALID_GUARDIAN_SET_CHANGE: &str = "01000000000100d90d6f9cbc0458599cbe4d267bc9221b54955b94cb5cb338aeb845bdc9dd275f558871ea479de9cc0b44cfb2a07344431a3adbd2f98aa86f4e12ff4aba061b7f00000007d00100000001018575df9b3c97b4e267deb92d93137844a97a0132";
|
||||
const ADDR_2: &str = "E06A9ADfeB38a8eE4D00E89307C016D0749679bD";
|
||||
const ADDR_3: &str = "8575Df9b3c97B4E267Deb92d93137844A97A0132";
|
||||
const ADDR_4: &str = "0427cDA59902Dc6EB0c1bd2b6D38F87c5552b348";
|
||||
const ADDR_5: &str = "bFEa822F75c42e1764c791B8fE04a7B10DDB3857";
|
||||
const ADDR_6: &str = "2F5FE0B158147e7260f14062556AfC94Eece55fF";
|
||||
const VAA_VALID_TRANSFER_1_SIG: &str = "01000000000100d106d4f363c6e3d0bf8ebf3cf8ef1ba35e66687b7613a826b5f5b68e0c346e1e0fdd6ceb332c87dad7d170ee6736571c0b75173787a8dcf41a492075e18a9a9601000007d01000000038010302010400000000000000000000000000000000000000000000000000000000000000000000000000000000000102030405060708090001020304050607080900010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000";
|
||||
const VAA_VALID_TRANSFER_2_SIGS: &str = "0100000000020040d91705d211c52c9f120adb1b794355ba10ec1ff855295e677c5b341b2e5449684179f8ca4087e88de2cba0e6cbf6e0c7a353529800ccf96e5fdd80a85a59220001efb8a4825c87ab68190e1b184eeda5c45f82b22450ff113f2581a2f1bd3aeca60798392405cd4d3b523a5c3426d09b963c195c842a0040e93651cb700785d0e600000007d0100000003801030201040000000000000000000000000000000000000000000000000000000000000000000000000000000000010203040506070809000102030405060708090002000000000000000000000000d833215cbcc3f914bd1c9ece3ee7bf8b14f841bb080000000000000000000000000000000000000000000000000de0b6b3a7640000";
|
||||
const VAA_VALID_TRANSFER_3_SIGS: &str = "0100000000030040d91705d211c52c9f120adb1b794355ba10ec1ff855295e677c5b341b2e5449684179f8ca4087e88de2cba0e6cbf6e0c7a353529800ccf96e5fdd80a85a59220001efb8a4825c87ab68190e1b184eeda5c45f82b22450ff113f2581a2f1bd3aeca60798392405cd4d3b523a5c3426d09b963c195c842a0040e93651cb700785d0e60002a5fb92ff2b5a5eed98e2909ed932e5d9328cb2527027cce8f40c4f5677c341c83fe9fac7bf39af60fe47ecfb6f52b22b9d817d24d4147684b08e2fe19ff3a3ef01000007d0100000003801030201040000000000000000000000000000000000000000000000000000000000000000000000000000000000010203040506070809000102030405060708090002000000000000000000000000d833215cbcc3f914bd1c9ece3ee7bf8b14f841bb080000000000000000000000000000000000000000000000000de0b6b3a7640000";
|
||||
const VAA_VALID_GUARDIAN_SET_CHANGE_FROM_0: &str = "01000000000100a33c022217ccb87a5bc83b71e6377fff6639e7904d9e9995a42dc0867dc2b0bc5d1aacc3752ea71cf4d85278526b5dd40b0343667a2d4434a44cbf7844181a1000000007d0010000000101e06a9adfeb38a8ee4d00e89307c016d0749679bd";
|
||||
const VAA_ERROR_SIGNATURE_SEQUENCE: &str = "01000000000201efb8a4825c87ab68190e1b184eeda5c45f82b22450ff113f2581a2f1bd3aeca60798392405cd4d3b523a5c3426d09b963c195c842a0040e93651cb700785d0e6000040d91705d211c52c9f120adb1b794355ba10ec1ff855295e677c5b341b2e5449684179f8ca4087e88de2cba0e6cbf6e0c7a353529800ccf96e5fdd80a85a592200000007d0100000003801030201040000000000000000000000000000000000000000000000000000000000000000000000000000000000010203040506070809000102030405060708090002000000000000000000000000d833215cbcc3f914bd1c9ece3ee7bf8b14f841bb080000000000000000000000000000000000000000000000000de0b6b3a7640000";
|
||||
const VAA_ERROR_WRONG_SIGNATURE_1_SIG: &str = "0100000000010075c1b20fb59adc55a08f9778bc525507a36a29d1f0e2cb3fcc9c90f7331786263c4bd53ce5d3865b4f63cddeafb2c1026b5e13f1b66af7dabbd1f1af9f34fd3f01000007d01000000038010302010400000000000000000000000000000000000000000000000000000000000000000000000000000000000102030405060708090001020304050607080900010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000";
|
||||
const VAA_VALID_GUARDIAN_SET_CHANGE_FROM_0_DIFF: &str = "01000000000100d90d6f9cbc0458599cbe4d267bc9221b54955b94cb5cb338aeb845bdc9dd275f558871ea479de9cc0b44cfb2a07344431a3adbd2f98aa86f4e12ff4aba061b7f00000007d00100000001018575df9b3c97b4e267deb92d93137844a97a0132";
|
||||
const VAA_ERROR_INVALID_TARGET_ADDRESS: &str = "0100000000010092f32c76aa3a8d83de59b3f2281cfbf70af33d9bcfbaa78bd3e9cafc512335ab40b126a894f0182ee8c69f5324496eb681c1780ed39bcc80f589cfc0a5df144a01000007d01000000038010302010400000000000000000000000000000000000000000000000000000000000000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000";
|
||||
const VAA_VALID_GUARDIAN_SET_CHANGE_JUMP: &str = "010000000001004b179853b36b76446c72944d50551be814ab34f23da2124615315da71505df801b38355d741cdd65e856792e2a1435270abfe52ae005c4e3671c0b7aac36445a01000007d00100000002018575df9b3c97b4e267deb92d93137844a97a0132";
|
||||
const VAA_ERROR_AMOUNT_TOO_HIGH: &str = "0100000000010055fdf76a64b779ac5b7a54dc181cf430f4d14a499b7933049d8bc94db529ed0a2d12d50ec2026883e59a5c64f2189b60c84a53b66113e8b52da66fd89f70495f00000007d01000000038010302010400000000000000000000000000000000000000000000000000000000000000000000000000000000000102030405060708090001020304050607080900010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000100000000000000000000000000000000";
|
||||
const VAA_ERROR_SAME_SOURCE_AND_TARGET: &str = "010000000001004c53dfce8fc9e781f0cfdc6592c00c337c1e109168ff17ee3bf4cf69ddb8a0a52a3c215093301d5459d282d625dc5125592609f06f14a57f61121e668b0ec10500000003e81000000038030302010400000000000000000000000000000000000000000000000000000000000000000000000000000000000102030405060708090001020304050607080900010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000";
|
||||
const VAA_ERROR_WRONG_TARGET: &str = "01000000000100b19a265b1407e9619ffc29be9562161ed2c155db5ba68e01265a250a677eb0c62bb91e468da827e9ec4c1e9428ade97129126f56500c4a3c9f9803cc85f656d200000003e81000000038010202010400000000000000000000000000000000000000000000000000000000000000000000000000000000000102030405060708090001020304050607080900010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000";
|
||||
const VAA_VALID_GUARDIAN_SET_CHANGE_TO_6: &str = "01000000000100a5defbd912ef327d07afff71e0da9c2e2a13e5516255c62e249a6761afe2465c7b6fc1032451559551e76eb4a029474fd791b2250c4fd40a8b3f5d4f5f58e5a30000000fa0010000000106befa429d57cd18b7f8a4d91a2da9ab4af05d0fbee06a9adfeb38a8ee4d00e89307c016d0749679bd8575df9b3c97b4e267deb92d93137844a97a01320427cda59902dc6eb0c1bd2b6d38f87c5552b348bfea822f75c42e1764c791b8fe04a7b10ddb38572f5fe0b158147e7260f14062556afc94eece55ff";
|
||||
const VAA_VALID_TRANSFER_5_SIGS_GS_1: &str = "01000000010500027eb7e87a9d0ab91ec53bb073c0f0acf189900139daa652666fd4cfe32a4ee42383c1a66e3a397c2de8ae485225357feb52f665952b1e384ef6dfcea1ba9f920001cfcacfad444ac3202f8f0d2252c69ee90d18c9105f7be3b5d361b7fcb0fbf7fa7287bac5de9cb02f86a28fdd7f24015991020431b0048aa3bbb29daed625e416000372f6c239ddeccded04a95a0cf0bfefe6e168148f1fe3b93e797eb2e74e098b890f2be341dd0f3c8172c2050154407cfdd1ea7bd6cce0b31f020ec7530ffb6109000449c025fe0630268983d57c4bd1546497788f810e427b6fd436cb1f048152375e1063422b4d1cc668a0612814c550ea7e3d1aa93404a0b6e089d210d4c937023a000548bf474fb350d5e482378c37404fb4d1421e262d13ebf6b11977214c789a246a6c278a522a9be4beba008f3d481b1ee35c5b0559bef474eb34b9e3e681947c230100000fa01000000039010302010500000000000000000000000000000000000000000000000000000000000000000000000000000000000102030405060708090001020304050607080900010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000";
|
||||
|
||||
const CANONICAL_LENGTH: usize = 20;
|
||||
|
||||
fn do_init_default_guardians<S: Storage, A: Api, Q: Querier>(deps: &mut Extern<S, A, Q>) {
|
||||
do_init(deps, &vec![GuardianAddress::from(ADDR_1)]);
|
||||
lazy_static! {
|
||||
static ref ALL_GUARDIANS: Vec<GuardianAddress> = vec![
|
||||
GuardianAddress::from(ADDR_1),
|
||||
GuardianAddress::from(ADDR_2),
|
||||
GuardianAddress::from(ADDR_3),
|
||||
GuardianAddress::from(ADDR_4),
|
||||
GuardianAddress::from(ADDR_5),
|
||||
GuardianAddress::from(ADDR_6)
|
||||
];
|
||||
}
|
||||
|
||||
fn unix_timestamp() -> u64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs()
|
||||
}
|
||||
|
||||
fn do_init_with_guardians<S: Storage, A: Api, Q: Querier>(
|
||||
deps: &mut Extern<S, A, Q>,
|
||||
number_of_guardians: usize,
|
||||
) {
|
||||
let expiration_time = unix_timestamp() + 1000;
|
||||
do_init(deps, &ALL_GUARDIANS[..number_of_guardians], expiration_time);
|
||||
}
|
||||
|
||||
fn do_init<S: Storage, A: Api, Q: Querier>(
|
||||
deps: &mut Extern<S, A, Q>,
|
||||
guardians: &Vec<GuardianAddress>,
|
||||
guardians: &[GuardianAddress],
|
||||
expiration_time: u64,
|
||||
) {
|
||||
let init_msg = InitMsg {
|
||||
initial_guardian_set: GuardianSetInfo {
|
||||
addresses: guardians.clone(),
|
||||
expiration_time: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 1000,
|
||||
addresses: guardians.to_vec(),
|
||||
expiration_time,
|
||||
},
|
||||
guardian_set_expirity: 50,
|
||||
wrapped_asset_code_id: 999,
|
||||
};
|
||||
let env = mock_env(&HumanAddr::from("creator"), &[]);
|
||||
let mut env = mock_env(&HumanAddr::from("creator"), &[]);
|
||||
env.block.time = unix_timestamp();
|
||||
let res = init(deps, env, init_msg).unwrap();
|
||||
assert_eq!(0, res.messages.len());
|
||||
|
||||
|
@ -602,7 +666,8 @@ mod tests {
|
|||
let msg = HandleMsg::SubmitVAA {
|
||||
vaa: hex::decode(vaa).expect("Decoding failed").into(),
|
||||
};
|
||||
let env = mock_env(&HumanAddr::from("creator"), &[]);
|
||||
let mut env = mock_env(&HumanAddr::from("creator"), &[]);
|
||||
env.block.time = unix_timestamp();
|
||||
|
||||
handle(deps, env, msg)
|
||||
}
|
||||
|
@ -610,15 +675,17 @@ mod tests {
|
|||
#[test]
|
||||
fn can_init() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_default_guardians(&mut deps);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_vaa_token_transfer() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_default_guardians(&mut deps);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let messages = submit_vaa(&mut deps, VAA_VALID_TRANSFER).unwrap().messages;
|
||||
let messages = submit_vaa(&mut deps, VAA_VALID_TRANSFER_1_SIG)
|
||||
.unwrap()
|
||||
.messages;
|
||||
assert_eq!(1, messages.len());
|
||||
let msg = &messages[0];
|
||||
match msg {
|
||||
|
@ -640,21 +707,39 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn same_vaa_twice_error() {
|
||||
fn valid_vaa_2_signatures() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_default_guardians(&mut deps);
|
||||
do_init_with_guardians(&mut deps, 2);
|
||||
|
||||
let _ = submit_vaa(&mut deps, VAA_VALID_TRANSFER).unwrap();
|
||||
let e = submit_vaa(&mut deps, VAA_VALID_TRANSFER).unwrap_err();
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_TRANSFER_2_SIGS);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_vaa_non_expiring_guardians() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init(&mut deps, &vec![GuardianAddress::from(ADDR_1)], 0);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_TRANSFER_1_SIG);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_same_vaa_twice() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let _ = submit_vaa(&mut deps, VAA_VALID_TRANSFER_1_SIG).unwrap();
|
||||
let e = submit_vaa(&mut deps, VAA_VALID_TRANSFER_1_SIG).unwrap_err();
|
||||
assert_eq!(e, ContractError::VaaAlreadyExecuted.std());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_vaa_guardian_set_change() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_default_guardians(&mut deps);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let messages = submit_vaa(&mut deps, VAA_VALID_GUARDIAN_SET_CHANGE)
|
||||
let messages = submit_vaa(&mut deps, VAA_VALID_GUARDIAN_SET_CHANGE_FROM_0)
|
||||
.unwrap()
|
||||
.messages;
|
||||
assert_eq!(0, messages.len());
|
||||
|
@ -674,4 +759,158 @@ mod tests {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_guardian_set_expired() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
// Expiration time 1 second in the past
|
||||
let expiration_time = unix_timestamp() - 1;
|
||||
do_init(
|
||||
&mut deps,
|
||||
&vec![GuardianAddress::from(ADDR_1)],
|
||||
expiration_time,
|
||||
);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_TRANSFER_1_SIG);
|
||||
assert_eq!(result, ContractError::GuardianSetExpired.std_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_no_quorum() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 2);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_TRANSFER_1_SIG);
|
||||
assert_eq!(result, ContractError::NoQuorum.std_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_partial_quorum() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 4);
|
||||
|
||||
// 3 signatures on 4-guardian set is quorum
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_TRANSFER_3_SIGS);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_wrong_guardian_index_order() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 2);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_ERROR_SIGNATURE_SEQUENCE);
|
||||
assert_eq!(result, ContractError::WrongGuardianIndexOrder.std_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_too_many_signatures() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_TRANSFER_2_SIGS);
|
||||
assert_eq!(result, ContractError::TooManySignatures.std_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_invalid_signature() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init(
|
||||
&mut deps,
|
||||
// Use 1-2-4 guardians
|
||||
&vec![
|
||||
GuardianAddress::from(ADDR_1),
|
||||
GuardianAddress::from(ADDR_2),
|
||||
GuardianAddress::from(ADDR_4),
|
||||
],
|
||||
unix_timestamp(),
|
||||
);
|
||||
// Sign by 1-2-3 guardians
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_TRANSFER_3_SIGS);
|
||||
assert_eq!(result, ContractError::GuardianSignatureError.std_err());
|
||||
|
||||
// Single signature, wrong key
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_ERROR_WRONG_SIGNATURE_1_SIG);
|
||||
assert_eq!(result, ContractError::GuardianSignatureError.std_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_not_current_quardian_set() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_GUARDIAN_SET_CHANGE_FROM_0);
|
||||
assert!(result.is_ok());
|
||||
|
||||
// Submit another valid change, which will fail, because now set #1 is active
|
||||
// (we need to send a different VAA, because otherwise it will be blocked by duplicate check)
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_GUARDIAN_SET_CHANGE_FROM_0_DIFF);
|
||||
assert_eq!(result, ContractError::NotCurrentGuardianSet.std_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_wrong_target_address_format() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_ERROR_INVALID_TARGET_ADDRESS);
|
||||
assert_eq!(result, ContractError::WrongTargetAddressFormat.std_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_guardian_set_change_index_not_increasing() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_GUARDIAN_SET_CHANGE_JUMP);
|
||||
assert_eq!(
|
||||
result,
|
||||
ContractError::GuardianSetIndexIncreaseError.std_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_transfer_amount_too_high() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_ERROR_AMOUNT_TOO_HIGH);
|
||||
assert_eq!(result, ContractError::AmountTooHigh.std_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_transfer_same_source_and_target() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_ERROR_SAME_SOURCE_AND_TARGET);
|
||||
assert_eq!(result, ContractError::SameSourceAndTarget.std_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn error_vaa_transfer_wrong_target_chain() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_ERROR_WRONG_TARGET);
|
||||
assert_eq!(result, ContractError::WrongTargetChain.std_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_transfer_after_guardian_set_change() {
|
||||
let mut deps = mock_dependencies(CANONICAL_LENGTH, &[]);
|
||||
do_init_with_guardians(&mut deps, 1);
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_TRANSFER_5_SIGS_GS_1);
|
||||
assert_eq!(result, ContractError::InvalidGuardianSetIndex.std_err());
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_GUARDIAN_SET_CHANGE_TO_6);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let result = submit_vaa(&mut deps, VAA_VALID_TRANSFER_5_SIGS_GS_1);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,14 @@ pub enum ContractError {
|
|||
/// Attempt to execute contract action while it is inactive
|
||||
#[error("ContractInactive")]
|
||||
ContractInactive,
|
||||
|
||||
/// Could not decode target address from canonical to human-readable form
|
||||
#[error("WrongTargetAddressFormat")]
|
||||
WrongTargetAddressFormat,
|
||||
|
||||
/// More signatures than active guardians found
|
||||
#[error("TooManySignatures")]
|
||||
TooManySignatures,
|
||||
}
|
||||
|
||||
impl ContractError {
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
mod byte_utils;
|
||||
pub mod contract;
|
||||
mod error;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use cosmwasm_std::{HumanAddr, Uint128, Binary};
|
||||
use cosmwasm_std::{Binary, HumanAddr, Uint128};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use cosmwasm_std::{CanonicalAddr, HumanAddr, StdResult, Storage, Binary};
|
||||
use cosmwasm_std::{Binary, CanonicalAddr, HumanAddr, StdResult, Storage};
|
||||
use cosmwasm_storage::{
|
||||
bucket, bucket_read, singleton, singleton_read, Bucket, ReadonlyBucket, ReadonlySingleton,
|
||||
Singleton,
|
||||
|
@ -122,7 +122,9 @@ mod tests {
|
|||
fn build_guardian_set(length: usize) -> GuardianSetInfo {
|
||||
let mut addresses: Vec<GuardianAddress> = Vec::with_capacity(length);
|
||||
for _ in 0..length {
|
||||
addresses.push(GuardianAddress{bytes: vec![].into()});
|
||||
addresses.push(GuardianAddress {
|
||||
bytes: vec![].into(),
|
||||
});
|
||||
}
|
||||
|
||||
GuardianSetInfo {
|
||||
|
@ -149,4 +151,4 @@ mod tests {
|
|||
assert_eq!(build_guardian_set(25).quorum(), 17);
|
||||
assert_eq!(build_guardian_set(100).quorum(), 67);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ static WASM: &[u8] = include_bytes!("../../../target/wasm32-unknown-unknown/rele
|
|||
use cosmwasm_std::{from_slice, Env, HumanAddr, InitResponse};
|
||||
use cosmwasm_storage::to_length_prefixed;
|
||||
use cosmwasm_vm::testing::{init, mock_env, mock_instance, MockApi, MockQuerier, MockStorage};
|
||||
use cosmwasm_vm::{Instance, Storage, Api};
|
||||
use cosmwasm_vm::{Api, Instance, Storage};
|
||||
|
||||
use wormhole::msg::InitMsg;
|
||||
use wormhole::state::{ConfigInfo, GuardianAddress, GuardianSetInfo, CONFIG_KEY};
|
||||
|
@ -53,7 +53,11 @@ fn do_init(
|
|||
wrapped_asset_code_id: 999,
|
||||
};
|
||||
let env = mock_env_height(&TestAddress::INITIALIZER.value(), height, 0);
|
||||
let owner = deps.api.canonical_address(&TestAddress::INITIALIZER.value()).0.unwrap();
|
||||
let owner = deps
|
||||
.api
|
||||
.canonical_address(&TestAddress::INITIALIZER.value())
|
||||
.0
|
||||
.unwrap();
|
||||
let res: InitResponse = init(&mut deps, env, init_msg).unwrap();
|
||||
assert_eq!(0, res.messages.len());
|
||||
|
||||
|
@ -66,7 +70,7 @@ fn do_init(
|
|||
guardian_set_expirity: 50,
|
||||
wrapped_asset_code_id: 999,
|
||||
owner,
|
||||
is_active: true,
|
||||
is_active: true,
|
||||
}
|
||||
);
|
||||
Ok(())
|
||||
|
@ -78,7 +82,9 @@ fn do_init(
|
|||
#[test]
|
||||
fn init_works() {
|
||||
let guardians = vec![GuardianAddress::from(GuardianAddress {
|
||||
bytes: hex::decode("beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe").expect("Decoding failed").into(),
|
||||
bytes: hex::decode("beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe")
|
||||
.expect("Decoding failed")
|
||||
.into(),
|
||||
})];
|
||||
let _deps = do_init(111, &guardians);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue