From 40c20026a85469dcba61c3eb18c0b874419378c9 Mon Sep 17 00:00:00 2001 From: axiongsupra Date: Sat, 26 Oct 2024 12:22:43 -0700 Subject: [PATCH] Format move code using aptos movefmt --- .../supra-framework/sources/account.move | 560 ++-- .../supra-framework/sources/account.spec.move | 440 ++- .../sources/aggregator/aggregator.move | 2 +- .../sources/aggregator/aggregator.spec.move | 22 +- .../aggregator/aggregator_factory.move | 22 +- .../aggregator/aggregator_factory.spec.move | 1 + .../aggregator/optional_aggregator.move | 29 +- .../aggregator/optional_aggregator.spec.move | 126 +- .../sources/aggregator_v2/aggregator_v2.move | 83 +- .../supra-framework/sources/block.move | 136 +- .../supra-framework/sources/block.spec.move | 30 +- .../supra-framework/sources/code.move | 287 +- .../supra-framework/sources/code.spec.move | 11 +- .../supra-framework/sources/coin.move | 1225 ++++---- .../supra-framework/sources/coin.spec.move | 199 +- .../sources/committee_map.move | 236 +- .../sources/configs/config_buffer.move | 12 +- .../sources/configs/config_buffer.spec.move | 21 +- .../sources/configs/consensus_config.move | 8 +- .../configs/consensus_config.spec.move | 11 +- .../sources/configs/execution_config.move | 5 +- .../configs/execution_config.spec.move | 6 +- .../sources/configs/gas_schedule.move | 69 +- .../sources/configs/gas_schedule.spec.move | 41 +- .../sources/configs/jwk_consensus_config.move | 54 +- .../configs/randomness_api_v0_config.move | 20 +- .../sources/configs/randomness_config.move | 53 +- .../configs/randomness_config_seqnum.move | 2 +- .../sources/configs/staking_config.move | 12 +- .../sources/configs/staking_config.spec.move | 90 +- .../sources/configs/supra_config.move | 8 +- .../sources/configs/supra_config.spec.move | 3 +- .../sources/configs/version.move | 24 +- .../sources/configs/version.spec.move | 6 +- .../sources/dispatchable_fungible_asset.move | 32 +- .../dispatchable_fungible_asset.spec.move | 2 +- .../supra-framework/sources/dkg.move | 38 +- .../supra-framework/sources/dkg.spec.move | 9 +- .../supra-framework/sources/event.move | 23 +- .../sources/function_info.move | 21 +- .../sources/function_info.spec.move | 2 +- .../sources/fungible_asset.move | 747 +++-- .../sources/fungible_asset.spec.move | 2 +- .../supra-framework/sources/genesis.move | 1015 ++++--- .../supra-framework/sources/genesis.spec.move | 10 +- .../supra-framework/sources/guid.move | 7 +- .../supra-framework/sources/jwks.move | 508 ++-- .../sources/keyless_account.move | 149 +- .../sources/keyless_account.spec.move | 2 +- .../supra-framework/sources/managed_coin.move | 65 +- .../sources/managed_coin.spec.move | 32 +- .../sources/multisig_account.move | 1236 +++++--- .../sources/multisig_account.spec.move | 57 +- .../sources/multisig_voting.move | 811 +++-- .../supra-framework/sources/object.move | 211 +- .../supra-framework/sources/object.spec.move | 269 +- .../sources/object_code_deployment.move | 42 +- .../sources/pbo_delegation_pool.move | 2609 +++++++++++------ .../sources/primary_fungible_store.move | 163 +- .../supra-framework/sources/randomness.move | 123 +- .../sources/randomness.spec.move | 25 +- .../sources/reconfiguration.move | 59 +- .../sources/reconfiguration.spec.move | 44 +- .../sources/reconfiguration_state.move | 25 +- .../sources/reconfiguration_state.spec.move | 82 +- .../sources/reconfiguration_with_dkg.move | 2 +- .../reconfiguration_with_dkg.spec.move | 8 +- .../sources/resource_account.move | 62 +- .../sources/resource_account.spec.move | 77 +- .../supra-framework/sources/stake.move | 1569 ++++++---- .../supra-framework/sources/stake.spec.move | 611 ++-- .../sources/staking_contract.move | 914 ++++-- .../sources/staking_contract.spec.move | 183 +- .../sources/staking_proxy.move | 279 +- .../sources/staking_proxy.spec.move | 66 +- .../sources/state_storage.move | 22 +- .../sources/state_storage.spec.move | 10 +- .../supra-framework/sources/storage_gas.move | 269 +- .../sources/storage_gas.spec.move | 58 +- .../sources/supra_account.move | 223 +- .../sources/supra_account.spec.move | 151 +- .../supra-framework/sources/supra_coin.move | 133 +- .../sources/supra_coin.spec.move | 9 +- .../sources/supra_governance.move | 483 ++- .../sources/system_addresses.move | 29 +- .../sources/system_addresses.spec.move | 1 + .../supra-framework/sources/timestamp.move | 20 +- .../sources/timestamp.spec.move | 6 +- .../sources/transaction_context.move | 111 +- .../sources/transaction_context.spec.move | 14 + .../sources/transaction_fee.move | 106 +- .../sources/transaction_fee.spec.move | 86 +- .../sources/transaction_validation.move | 162 +- .../sources/transaction_validation.spec.move | 210 +- .../sources/validator_consensus_info.move | 15 +- .../supra-framework/sources/vesting.move | 1119 ++++--- .../supra-framework/sources/vesting.spec.move | 222 +- .../sources/vesting_without_staking.move | 1192 +++++--- .../sources/vesting_without_staking.spec.move | 103 +- .../supra-framework/sources/voting.move | 597 ++-- .../supra-framework/sources/voting.spec.move | 324 +- 101 files changed, 13799 insertions(+), 7921 deletions(-) diff --git a/aptos-move/framework/supra-framework/sources/account.move b/aptos-move/framework/supra-framework/sources/account.move index 5e7894a54a4fd..32278da508946 100644 --- a/aptos-move/framework/supra-framework/sources/account.move +++ b/aptos-move/framework/supra-framework/sources/account.move @@ -27,7 +27,7 @@ module supra_framework::account { struct KeyRotation has drop, store { account: address, old_authentication_key: vector, - new_authentication_key: vector, + new_authentication_key: vector } /// Resource representing an account. @@ -38,23 +38,29 @@ module supra_framework::account { coin_register_events: EventHandle, key_rotation_events: EventHandle, rotation_capability_offer: CapabilityOffer, - signer_capability_offer: CapabilityOffer, + signer_capability_offer: CapabilityOffer } struct KeyRotationEvent has drop, store { old_authentication_key: vector, - new_authentication_key: vector, + new_authentication_key: vector } struct CoinRegisterEvent has drop, store { - type_info: TypeInfo, + type_info: TypeInfo } - struct CapabilityOffer has store { for: Option
} + struct CapabilityOffer has store { + for: Option
+ } - struct RotationCapability has drop, store { account: address } + struct RotationCapability has drop, store { + account: address + } - struct SignerCapability has drop, store { account: address } + struct SignerCapability has drop, store { + account: address + } /// It is easy to fetch the authentication key of an address by simply reading it from the `Account` struct at that address. /// The table in this struct makes it possible to do a reverse lookup: it maps an authentication key, to the address of the account which has that authentication key set. @@ -68,7 +74,7 @@ module supra_framework::account { /// The recovered address would no longer be 'a'; it would be `b`, which is incorrect. /// This struct solves this problem by mapping the new authentication key `b` to the original address `a` and thus helping the wallet software during recovery find the correct address. struct OriginatingAddress has key { - address_map: Table, + address_map: Table } /// This structs stores the challenge message that should be signed during key rotation. First, this struct is @@ -83,20 +89,20 @@ module supra_framework::account { // the address of the account whose key is being rotated current_auth_key: address, // the current authentication key of the account whose key is being rotated - new_public_key: vector, + new_public_key: vector // the new public key that the account owner wants to rotate to } /// Deprecated struct - newest version is `RotationCapabilityOfferProofChallengeV2` struct RotationCapabilityOfferProofChallenge has drop { sequence_number: u64, - recipient_address: address, + recipient_address: address } /// Deprecated struct - newest version is `SignerCapabilityOfferProofChallengeV2` struct SignerCapabilityOfferProofChallenge has drop { sequence_number: u64, - recipient_address: address, + recipient_address: address } /// This struct stores the challenge message that should be signed by the source account, when the source account @@ -106,13 +112,13 @@ module supra_framework::account { chain_id: u8, sequence_number: u64, source_address: address, - recipient_address: address, + recipient_address: address } struct SignerCapabilityOfferProofChallengeV2 has copy, drop { sequence_number: u64, source_address: address, - recipient_address: address, + recipient_address: address } const MAX_U64: u128 = 18446744073709551615; @@ -175,14 +181,14 @@ module supra_framework::account { #[test_only] /// Create signer for testing, independently of an Aptos-style `Account`. - public fun create_signer_for_test(addr: address): signer { create_signer(addr) } + public fun create_signer_for_test(addr: address): signer { + create_signer(addr) + } /// Only called during genesis to initialize system resources for this module. public(friend) fun initialize(supra_framework: &signer) { system_addresses::assert_supra_framework(supra_framework); - move_to(supra_framework, OriginatingAddress { - address_map: table::new(), - }); + move_to(supra_framework, OriginatingAddress { address_map: table::new() }); } public fun create_account_if_does_not_exist(account_address: address) { @@ -196,11 +202,15 @@ module supra_framework::account { /// `new_address`. public(friend) fun create_account(new_address: address): signer { // there cannot be an Account resource under new_addr already. - assert!(!exists(new_address), error::already_exists(EACCOUNT_ALREADY_EXISTS)); + assert!( + !exists(new_address), error::already_exists(EACCOUNT_ALREADY_EXISTS) + ); // NOTE: @core_resources gets created via a `create_account` call, so we do not include it below. assert!( - new_address != @vm_reserved && new_address != @supra_framework && new_address != @aptos_token, + new_address != @vm_reserved + && new_address != @supra_framework + && new_address != @aptos_token, error::invalid_argument(ECANNOT_RESERVED_ADDRESS) ); @@ -218,10 +228,12 @@ module supra_framework::account { let guid_creation_num = 0; let guid_for_coin = guid::create(new_address, &mut guid_creation_num); - let coin_register_events = event::new_event_handle(guid_for_coin); + let coin_register_events = + event::new_event_handle(guid_for_coin); let guid_for_rotation = guid::create(new_address, &mut guid_creation_num); - let key_rotation_events = event::new_event_handle(guid_for_rotation); + let key_rotation_events = + event::new_event_handle(guid_for_rotation); move_to( &new_account, @@ -232,7 +244,7 @@ module supra_framework::account { coin_register_events, key_rotation_events, rotation_capability_offer: CapabilityOffer { for: option::none() }, - signer_capability_offer: CapabilityOffer { for: option::none() }, + signer_capability_offer: CapabilityOffer { for: option::none() } } ); @@ -275,7 +287,9 @@ module supra_framework::account { /// 1. During normal key rotation via `rotate_authentication_key` or `rotate_authentication_key_call` /// 2. During resource account initialization so that no private key can control the resource account /// 3. During multisig_v2 account creation - public(friend) fun rotate_authentication_key_internal(account: &signer, new_auth_key: vector) acquires Account { + public(friend) fun rotate_authentication_key_internal( + account: &signer, new_auth_key: vector + ) acquires Account { let addr = signer::address_of(account); assert!(exists_at(addr), error::not_found(EACCOUNT_DOES_NOT_EXIST)); assert!( @@ -291,7 +305,9 @@ module supra_framework::account { /// does not come with a proof-of-knowledge of the underlying SK. Nonetheless, we need this functionality due to /// the introduction of non-standard key algorithms, such as passkeys, which cannot produce proofs-of-knowledge in /// the format expected in `rotate_authentication_key`. - entry fun rotate_authentication_key_call(account: &signer, new_auth_key: vector) acquires Account { + entry fun rotate_authentication_key_call( + account: &signer, new_auth_key: vector + ) acquires Account { rotate_authentication_key_internal(account, new_auth_key); } @@ -330,7 +346,7 @@ module supra_framework::account { to_scheme: u8, to_public_key_bytes: vector, cap_rotate_key: vector, - cap_update_table: vector, + cap_update_table: vector ) acquires Account, OriginatingAddress { let addr = signer::address_of(account); assert!(exists_at(addr), error::not_found(EACCOUNT_DOES_NOT_EXIST)); @@ -338,15 +354,21 @@ module supra_framework::account { // Verify the given `from_public_key_bytes` matches this account's current authentication key. if (from_scheme == ED25519_SCHEME) { - let from_pk = ed25519::new_unvalidated_public_key_from_bytes(from_public_key_bytes); - let from_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&from_pk); + let from_pk = + ed25519::new_unvalidated_public_key_from_bytes(from_public_key_bytes); + let from_auth_key = + ed25519::unvalidated_public_key_to_authentication_key(&from_pk); assert!( account_resource.authentication_key == from_auth_key, error::unauthenticated(EWRONG_CURRENT_PUBLIC_KEY) ); } else if (from_scheme == MULTI_ED25519_SCHEME) { - let from_pk = multi_ed25519::new_unvalidated_public_key_from_bytes(from_public_key_bytes); - let from_auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&from_pk); + let from_pk = + multi_ed25519::new_unvalidated_public_key_from_bytes( + from_public_key_bytes + ); + let from_auth_key = + multi_ed25519::unvalidated_public_key_to_authentication_key(&from_pk); assert!( account_resource.authentication_key == from_auth_key, error::unauthenticated(EWRONG_CURRENT_PUBLIC_KEY) @@ -356,12 +378,13 @@ module supra_framework::account { }; // Construct a valid `RotationProofChallenge` that `cap_rotate_key` and `cap_update_table` will validate against. - let curr_auth_key_as_address = from_bcs::to_address(account_resource.authentication_key); + let curr_auth_key_as_address = + from_bcs::to_address(account_resource.authentication_key); let challenge = RotationProofChallenge { sequence_number: account_resource.sequence_number, originator: addr, current_auth_key: curr_auth_key_as_address, - new_public_key: to_public_key_bytes, + new_public_key: to_public_key_bytes }; // Assert the challenges signed by the current and new keys are valid @@ -371,15 +394,18 @@ module supra_framework::account { cap_rotate_key, &challenge ); - let new_auth_key = assert_valid_rotation_proof_signature_and_get_auth_key( - to_scheme, - to_public_key_bytes, - cap_update_table, - &challenge - ); + let new_auth_key = + assert_valid_rotation_proof_signature_and_get_auth_key( + to_scheme, + to_public_key_bytes, + cap_update_table, + &challenge + ); // Update the `OriginatingAddress` table. - update_auth_key_and_originating_address_table(addr, account_resource, new_auth_key); + update_auth_key_and_originating_address_table( + addr, account_resource, new_auth_key + ); } public entry fun rotate_authentication_key_with_rotation_capability( @@ -389,34 +415,43 @@ module supra_framework::account { new_public_key_bytes: vector, cap_update_table: vector ) acquires Account, OriginatingAddress { - assert!(exists_at(rotation_cap_offerer_address), error::not_found(EOFFERER_ADDRESS_DOES_NOT_EXIST)); + assert!( + exists_at(rotation_cap_offerer_address), + error::not_found(EOFFERER_ADDRESS_DOES_NOT_EXIST) + ); // Check that there exists a rotation capability offer at the offerer's account resource for the delegate. let delegate_address = signer::address_of(delegate_signer); - let offerer_account_resource = borrow_global(rotation_cap_offerer_address); + let offerer_account_resource = + borrow_global(rotation_cap_offerer_address); assert!( - option::contains(&offerer_account_resource.rotation_capability_offer.for, &delegate_address), + option::contains( + &offerer_account_resource.rotation_capability_offer.for, &delegate_address + ), error::not_found(ENO_SUCH_ROTATION_CAPABILITY_OFFER) ); - let curr_auth_key = from_bcs::to_address(offerer_account_resource.authentication_key); + let curr_auth_key = + from_bcs::to_address(offerer_account_resource.authentication_key); let challenge = RotationProofChallenge { sequence_number: get_sequence_number(delegate_address), originator: rotation_cap_offerer_address, current_auth_key: curr_auth_key, - new_public_key: new_public_key_bytes, + new_public_key: new_public_key_bytes }; // Verifies that the `RotationProofChallenge` from above is signed under the new public key that we are rotating to. l - let new_auth_key = assert_valid_rotation_proof_signature_and_get_auth_key( - new_scheme, - new_public_key_bytes, - cap_update_table, - &challenge - ); + let new_auth_key = + assert_valid_rotation_proof_signature_and_get_auth_key( + new_scheme, + new_public_key_bytes, + cap_update_table, + &challenge + ); // Update the `OriginatingAddress` table, so we can find the originating address using the new address. - let offerer_account_resource = borrow_global_mut(rotation_cap_offerer_address); + let offerer_account_resource = + borrow_global_mut(rotation_cap_offerer_address); update_auth_key_and_originating_address_table( rotation_cap_offerer_address, offerer_account_resource, @@ -446,7 +481,7 @@ module supra_framework::account { rotation_capability_sig_bytes: vector, account_scheme: u8, account_public_key_bytes: vector, - recipient_address: address, + recipient_address: address ) acquires Account { let addr = signer::address_of(account); assert!(exists_at(recipient_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); @@ -457,34 +492,46 @@ module supra_framework::account { chain_id: chain_id::get(), sequence_number: account_resource.sequence_number, source_address: addr, - recipient_address, + recipient_address }; // verify the signature on `RotationCapabilityOfferProofChallengeV2` by the account owner if (account_scheme == ED25519_SCHEME) { - let pubkey = ed25519::new_unvalidated_public_key_from_bytes(account_public_key_bytes); - let expected_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&pubkey); + let pubkey = + ed25519::new_unvalidated_public_key_from_bytes(account_public_key_bytes); + let expected_auth_key = + ed25519::unvalidated_public_key_to_authentication_key(&pubkey); assert!( account_resource.authentication_key == expected_auth_key, error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY) ); - let rotation_capability_sig = ed25519::new_signature_from_bytes(rotation_capability_sig_bytes); + let rotation_capability_sig = + ed25519::new_signature_from_bytes(rotation_capability_sig_bytes); assert!( - ed25519::signature_verify_strict_t(&rotation_capability_sig, &pubkey, proof_challenge), + ed25519::signature_verify_strict_t( + &rotation_capability_sig, &pubkey, proof_challenge + ), error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE) ); } else if (account_scheme == MULTI_ED25519_SCHEME) { - let pubkey = multi_ed25519::new_unvalidated_public_key_from_bytes(account_public_key_bytes); - let expected_auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&pubkey); + let pubkey = + multi_ed25519::new_unvalidated_public_key_from_bytes( + account_public_key_bytes + ); + let expected_auth_key = + multi_ed25519::unvalidated_public_key_to_authentication_key(&pubkey); assert!( account_resource.authentication_key == expected_auth_key, error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY) ); - let rotation_capability_sig = multi_ed25519::new_signature_from_bytes(rotation_capability_sig_bytes); + let rotation_capability_sig = + multi_ed25519::new_signature_from_bytes(rotation_capability_sig_bytes); assert!( - multi_ed25519::signature_verify_strict_t(&rotation_capability_sig, &pubkey, proof_challenge), + multi_ed25519::signature_verify_strict_t( + &rotation_capability_sig, &pubkey, proof_challenge + ), error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE) ); } else { @@ -492,7 +539,9 @@ module supra_framework::account { }; // update the existing rotation capability offer or put in a new rotation capability offer for the current account - option::swap_or_fill(&mut account_resource.rotation_capability_offer.for, recipient_address); + option::swap_or_fill( + &mut account_resource.rotation_capability_offer.for, recipient_address + ); } #[view] @@ -508,18 +557,24 @@ module supra_framework::account { let account_resource = borrow_global(account_addr); assert!( option::is_some(&account_resource.rotation_capability_offer.for), - error::not_found(ENO_SIGNER_CAPABILITY_OFFERED), + error::not_found(ENO_SIGNER_CAPABILITY_OFFERED) ); *option::borrow(&account_resource.rotation_capability_offer.for) } /// Revoke the rotation capability offer given to `to_be_revoked_recipient_address` from `account` - public entry fun revoke_rotation_capability(account: &signer, to_be_revoked_address: address) acquires Account { - assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); + public entry fun revoke_rotation_capability( + account: &signer, to_be_revoked_address: address + ) acquires Account { + assert!( + exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST) + ); let addr = signer::address_of(account); let account_resource = borrow_global_mut(addr); assert!( - option::contains(&account_resource.rotation_capability_offer.for, &to_be_revoked_address), + option::contains( + &account_resource.rotation_capability_offer.for, &to_be_revoked_address + ), error::not_found(ENO_SUCH_ROTATION_CAPABILITY_OFFER) ); revoke_any_rotation_capability(account); @@ -554,14 +609,21 @@ module supra_framework::account { let proof_challenge = SignerCapabilityOfferProofChallengeV2 { sequence_number: get_sequence_number(source_address), source_address, - recipient_address, + recipient_address }; verify_signed_message( - source_address, account_scheme, account_public_key_bytes, signer_capability_sig_bytes, proof_challenge); + source_address, + account_scheme, + account_public_key_bytes, + signer_capability_sig_bytes, + proof_challenge + ); // Update the existing signer capability offer or put in a new signer capability offer for the recipient. let account_resource = borrow_global_mut(source_address); - option::swap_or_fill(&mut account_resource.signer_capability_offer.for, recipient_address); + option::swap_or_fill( + &mut account_resource.signer_capability_offer.for, recipient_address + ); } #[view] @@ -577,19 +639,25 @@ module supra_framework::account { let account_resource = borrow_global(account_addr); assert!( option::is_some(&account_resource.signer_capability_offer.for), - error::not_found(ENO_SIGNER_CAPABILITY_OFFERED), + error::not_found(ENO_SIGNER_CAPABILITY_OFFERED) ); *option::borrow(&account_resource.signer_capability_offer.for) } /// Revoke the account owner's signer capability offer for `to_be_revoked_address` (i.e., the address that /// has a signer capability offer from `account` but will be revoked in this function). - public entry fun revoke_signer_capability(account: &signer, to_be_revoked_address: address) acquires Account { - assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); + public entry fun revoke_signer_capability( + account: &signer, to_be_revoked_address: address + ) acquires Account { + assert!( + exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST) + ); let addr = signer::address_of(account); let account_resource = borrow_global_mut(addr); assert!( - option::contains(&account_resource.signer_capability_offer.for, &to_be_revoked_address), + option::contains( + &account_resource.signer_capability_offer.for, &to_be_revoked_address + ), error::not_found(ENO_SUCH_SIGNER_CAPABILITY) ); revoke_any_signer_capability(account); @@ -603,8 +671,12 @@ module supra_framework::account { /// Return an authorized signer of the offerer, if there's an existing signer capability offer for `account` /// at the offerer's address. - public fun create_authorized_signer(account: &signer, offerer_address: address): signer acquires Account { - assert!(exists_at(offerer_address), error::not_found(EOFFERER_ADDRESS_DOES_NOT_EXIST)); + public fun create_authorized_signer( + account: &signer, offerer_address: address + ): signer acquires Account { + assert!( + exists_at(offerer_address), error::not_found(EOFFERER_ADDRESS_DOES_NOT_EXIST) + ); // Check if there's an existing signer capability offer from the offerer. let account_resource = borrow_global(offerer_address); @@ -635,7 +707,8 @@ module supra_framework::account { ); ed25519::unvalidated_public_key_to_authentication_key(&pk) } else if (scheme == MULTI_ED25519_SCHEME) { - let pk = multi_ed25519::new_unvalidated_public_key_from_bytes(public_key_bytes); + let pk = + multi_ed25519::new_unvalidated_public_key_from_bytes(public_key_bytes); let sig = multi_ed25519::new_signature_from_bytes(signature); assert!( multi_ed25519::signature_verify_strict_t(&sig, &pk, *challenge), @@ -652,9 +725,10 @@ module supra_framework::account { fun update_auth_key_and_originating_address_table( originating_addr: address, account_resource: &mut Account, - new_auth_key_vector: vector, + new_auth_key_vector: vector ) acquires OriginatingAddress { - let address_map = &mut borrow_global_mut(@supra_framework).address_map; + let address_map = + &mut borrow_global_mut(@supra_framework).address_map; let curr_auth_key = from_bcs::to_address(account_resource.authentication_key); // Checks `OriginatingAddress[curr_auth_key]` is either unmapped, or mapped to `originating_address`. @@ -681,17 +755,19 @@ module supra_framework::account { table::add(address_map, new_auth_key, originating_addr); if (std::features::module_event_migration_enabled()) { - event::emit(KeyRotation { - account: originating_addr, - old_authentication_key: account_resource.authentication_key, - new_authentication_key: new_auth_key_vector, - }); + event::emit( + KeyRotation { + account: originating_addr, + old_authentication_key: account_resource.authentication_key, + new_authentication_key: new_auth_key_vector + } + ); }; event::emit_event( &mut account_resource.key_rotation_events, KeyRotationEvent { old_authentication_key: account_resource.authentication_key, - new_authentication_key: new_auth_key_vector, + new_authentication_key: new_auth_key_vector } ); @@ -721,22 +797,25 @@ module supra_framework::account { /// yet to execute any transactions and that the `Account::signer_capability_offer::for` is none. The probability of a /// collision where someone has legitimately produced a private key that maps to a resource account address is less /// than `(1/2)^(256)`. - public fun create_resource_account(source: &signer, seed: vector): (signer, SignerCapability) acquires Account { + public fun create_resource_account( + source: &signer, seed: vector + ): (signer, SignerCapability) acquires Account { let resource_addr = create_resource_address(&signer::address_of(source), seed); - let resource = if (exists_at(resource_addr)) { - let account = borrow_global(resource_addr); - assert!( - option::is_none(&account.signer_capability_offer.for), - error::already_exists(ERESOURCE_ACCCOUNT_EXISTS), - ); - assert!( - account.sequence_number == 0, - error::invalid_state(EACCOUNT_ALREADY_USED), - ); - create_signer(resource_addr) - } else { - create_account_unchecked(resource_addr) - }; + let resource = + if (exists_at(resource_addr)) { + let account = borrow_global(resource_addr); + assert!( + option::is_none(&account.signer_capability_offer.for), + error::already_exists(ERESOURCE_ACCCOUNT_EXISTS) + ); + assert!( + account.sequence_number == 0, + error::invalid_state(EACCOUNT_ALREADY_USED) + ); + create_signer(resource_addr) + } else { + create_account_unchecked(resource_addr) + }; // By default, only the SignerCapability should have control over the resource account and not the auth key. // If the source account wants direct control via auth key, they would need to explicitly rotate the auth key @@ -750,19 +829,20 @@ module supra_framework::account { } /// create the account for system reserved addresses - public(friend) fun create_framework_reserved_account(addr: address): (signer, SignerCapability) { + public(friend) fun create_framework_reserved_account(addr: address): + (signer, SignerCapability) { assert!( - addr == @0x1 || - addr == @0x2 || - addr == @0x3 || - addr == @0x4 || - addr == @0x5 || - addr == @0x6 || - addr == @0x7 || - addr == @0x8 || - addr == @0x9 || - addr == @0xa, - error::permission_denied(ENO_VALID_FRAMEWORK_RESERVED_ADDRESS), + addr == @0x1 + || addr == @0x2 + || addr == @0x3 + || addr == @0x4 + || addr == @0x5 + || addr == @0x6 + || addr == @0x7 + || addr == @0x8 + || addr == @0x9 + || addr == @0xa, + error::permission_denied(ENO_VALID_FRAMEWORK_RESERVED_ADDRESS) ); let signer = create_account_unchecked(addr); let signer_cap = SignerCapability { account: addr }; @@ -779,7 +859,7 @@ module supra_framework::account { let guid = guid::create(addr, &mut account.guid_creation_num); assert!( account.guid_creation_num < MAX_GUID_CREATION_NUM, - error::out_of_range(EEXCEEDED_MAX_GUID_CREATION_NUM), + error::out_of_range(EEXCEEDED_MAX_GUID_CREATION_NUM) ); guid } @@ -801,8 +881,8 @@ module supra_framework::account { event::emit_event( &mut account.coin_register_events, CoinRegisterEvent { - type_info: type_info::type_of(), - }, + type_info: type_info::type_of() + } ); } @@ -812,13 +892,12 @@ module supra_framework::account { #[test_only] public fun get_signer_capability_offer_proof_challenge_v2( - source_address: address, - recipient_address: address, + source_address: address, recipient_address: address ): SignerCapabilityOfferProofChallengeV2 acquires Account { SignerCapabilityOfferProofChallengeV2 { sequence_number: borrow_global_mut(source_address).sequence_number, source_address, - recipient_address, + recipient_address } } @@ -826,12 +905,16 @@ module supra_framework::account { /// Capability based functions for efficient use. /////////////////////////////////////////////////////////////////////////// - public fun create_signer_with_capability(capability: &SignerCapability): signer { + public fun create_signer_with_capability( + capability: &SignerCapability + ): signer { let addr = &capability.account; create_signer(*addr) } - public fun get_signer_capability_address(capability: &SignerCapability): address { + public fun get_signer_capability_address( + capability: &SignerCapability + ): address { capability.account } @@ -840,35 +923,45 @@ module supra_framework::account { account_scheme: u8, account_public_key: vector, signed_message_bytes: vector, - message: T, + message: T ) acquires Account { let account_resource = borrow_global_mut(account); // Verify that the `SignerCapabilityOfferProofChallengeV2` has the right information and is signed by the account owner's key if (account_scheme == ED25519_SCHEME) { - let pubkey = ed25519::new_unvalidated_public_key_from_bytes(account_public_key); - let expected_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&pubkey); + let pubkey = + ed25519::new_unvalidated_public_key_from_bytes(account_public_key); + let expected_auth_key = + ed25519::unvalidated_public_key_to_authentication_key(&pubkey); assert!( account_resource.authentication_key == expected_auth_key, - error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY), + error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY) ); - let signer_capability_sig = ed25519::new_signature_from_bytes(signed_message_bytes); + let signer_capability_sig = + ed25519::new_signature_from_bytes(signed_message_bytes); assert!( - ed25519::signature_verify_strict_t(&signer_capability_sig, &pubkey, message), - error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE), + ed25519::signature_verify_strict_t( + &signer_capability_sig, &pubkey, message + ), + error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE) ); } else if (account_scheme == MULTI_ED25519_SCHEME) { - let pubkey = multi_ed25519::new_unvalidated_public_key_from_bytes(account_public_key); - let expected_auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&pubkey); + let pubkey = + multi_ed25519::new_unvalidated_public_key_from_bytes(account_public_key); + let expected_auth_key = + multi_ed25519::unvalidated_public_key_to_authentication_key(&pubkey); assert!( account_resource.authentication_key == expected_auth_key, - error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY), + error::invalid_argument(EWRONG_CURRENT_PUBLIC_KEY) ); - let signer_capability_sig = multi_ed25519::new_signature_from_bytes(signed_message_bytes); + let signer_capability_sig = + multi_ed25519::new_signature_from_bytes(signed_message_bytes); assert!( - multi_ed25519::signature_verify_strict_t(&signer_capability_sig, &pubkey, message), - error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE), + multi_ed25519::signature_verify_strict_t( + &signer_capability_sig, &pubkey, message + ), + error::invalid_argument(EINVALID_PROOF_OF_KNOWLEDGE) ); } else { abort error::invalid_argument(EINVALID_SCHEME) @@ -894,7 +987,8 @@ module supra_framework::account { #[test(user = @0x1)] public entry fun test_create_resource_account(user: signer) acquires Account { - let (resource_account, resource_account_cap) = create_resource_account(&user, x"01"); + let (resource_account, resource_account_cap) = + create_resource_account(&user, x"01"); let resource_addr = signer::address_of(&resource_account); assert!(resource_addr != signer::address_of(&user), 0); assert!(resource_addr == get_signer_capability_address(&resource_account_cap), 1); @@ -903,7 +997,8 @@ module supra_framework::account { #[test] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_cannot_control_resource_account_via_auth_key() acquires Account { - let alice_pk = x"4141414141414141414141414141414141414141414141414141414141414145"; + let alice_pk = + x"4141414141414141414141414141414141414141414141414141414141414145"; let alice = create_account_from_ed25519_public_key(alice_pk); let alice_auth = get_authentication_key(signer::address_of(&alice)); // must look like a valid public key @@ -921,7 +1016,7 @@ module supra_framework::account { let proof_challenge = SignerCapabilityOfferProofChallengeV2 { sequence_number: borrow_global_mut(resource_addr).sequence_number, source_address: resource_addr, - recipient_address, + recipient_address }; let eve_sig = ed25519::sign_struct(&eve_sk, copy proof_challenge); @@ -930,14 +1025,18 @@ module supra_framework::account { let account_public_key_bytes = alice_auth; vector::append(&mut account_public_key_bytes, eve_pk_bytes); vector::push_back(&mut account_public_key_bytes, 1); // Multisig verification threshold. - let fake_pk = multi_ed25519::new_unvalidated_public_key_from_bytes(account_public_key_bytes); + let fake_pk = + multi_ed25519::new_unvalidated_public_key_from_bytes(account_public_key_bytes); // Construct a multisig for `proof_challenge` as if it is signed by the signers behind `fake_pk`, // Eve being the only participant. let signer_capability_sig_bytes = x""; - vector::append(&mut signer_capability_sig_bytes, ed25519::signature_to_bytes(&eve_sig)); + vector::append( + &mut signer_capability_sig_bytes, ed25519::signature_to_bytes(&eve_sig) + ); vector::append(&mut signer_capability_sig_bytes, x"40000000"); // Signers bitmap. - let fake_sig = multi_ed25519::new_signature_from_bytes(signer_capability_sig_bytes); + let fake_sig = + multi_ed25519::new_signature_from_bytes(signer_capability_sig_bytes); assert!( multi_ed25519::signature_verify_strict_t(&fake_sig, &fake_pk, proof_challenge), @@ -989,26 +1088,21 @@ module supra_framework::account { #[test_only] /// Increment sequence number of account at address `addr` public fun increment_sequence_number_for_test_using_source_code( - addr: address, + addr: address ) acquires Account { increment_sequence_number(addr); } #[test_only] /// Increment sequence number of account at address `addr` - public fun increment_sequence_number_for_test( - addr: address, - ) acquires Account { + public fun increment_sequence_number_for_test(addr: address) acquires Account { let acct = borrow_global_mut(addr); acct.sequence_number = acct.sequence_number + 1; } #[test_only] /// Update address `addr` to have `s` as its sequence number - public fun set_sequence_number( - addr: address, - s: u64 - ) acquires Account { + public fun set_sequence_number(addr: address, s: u64) acquires Account { borrow_global_mut(addr).sequence_number = s; } @@ -1018,21 +1112,26 @@ module supra_framework::account { } #[test_only] - public fun set_signer_capability_offer(offerer: address, receiver: address) acquires Account { + public fun set_signer_capability_offer( + offerer: address, receiver: address + ) acquires Account { let account_resource = borrow_global_mut(offerer); option::swap_or_fill(&mut account_resource.signer_capability_offer.for, receiver); } #[test_only] - public fun set_rotation_capability_offer(offerer: address, receiver: address) acquires Account { + public fun set_rotation_capability_offer( + offerer: address, receiver: address + ) acquires Account { let account_resource = borrow_global_mut(offerer); - option::swap_or_fill(&mut account_resource.rotation_capability_offer.for, receiver); + option::swap_or_fill( + &mut account_resource.rotation_capability_offer.for, receiver + ); } #[test] /// Verify test-only sequence number mocking - public entry fun mock_sequence_numbers() - acquires Account { + public entry fun mock_sequence_numbers() acquires Account { let addr: address = @0x1234; // Define test address create_account(addr); // Initialize account resource // Assert sequence number intializes to 0 @@ -1047,8 +1146,7 @@ module supra_framework::account { #[test] /// Verify source-code sequence number mocking - public entry fun mock_sequence_numbers_source_code() - acquires Account { + public entry fun mock_sequence_numbers_source_code() acquires Account { let addr: address = @0x1234; // Define test address create_account(addr); // Initialize account resource // Assert sequence number intializes to 0 @@ -1070,20 +1168,27 @@ module supra_framework::account { public entry fun test_empty_public_key(alice: signer) acquires Account, OriginatingAddress { create_account(signer::address_of(&alice)); let pk = vector::empty(); - let sig = x"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - rotate_authentication_key(&alice, ED25519_SCHEME, pk, ED25519_SCHEME, pk, sig, sig); + let sig = + x"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + rotate_authentication_key( + &alice, ED25519_SCHEME, pk, ED25519_SCHEME, pk, sig, sig + ); } #[test(alice_address = @0xa11ce)] #[expected_failure(abort_code = 524289, location = supra_framework::account)] - public entry fun test_create_account_twice_should_fail(alice_address: address) { + public entry fun test_create_account_twice_should_fail( + alice_address: address + ) { create_account_if_does_not_exist(alice_address); create_account(alice_address); } #[test(alice_address = @0xa11ce)] #[expected_failure(abort_code = 65541, location = supra_framework::account)] - public entry fun test_create_account_with_core_resource_address_should_fail(alice_address: address) { + public entry fun test_create_account_with_core_resource_address_should_fail( + alice_address: address + ) { create_account(alice_address); create_account(@supra_framework); create_account(@aptos_token); @@ -1092,7 +1197,9 @@ module supra_framework::account { #[test(alice_address = @0xa11ce)] #[expected_failure(abort_code = 327691, location = supra_framework::account)] - public entry fun test_create_framework_reserved_account_with_core_resource_address_should_fail(alice_address: address) { + public entry fun test_create_framework_reserved_account_with_core_resource_address_should_fail( + alice_address: address + ) { create_framework_reserved_account(alice_address); } @@ -1102,11 +1209,21 @@ module supra_framework::account { create_account(signer::address_of(&alice)); let test_signature = vector::empty(); let pk = x"0000000000000000000000000000000000000000000000000000000000000000"; - rotate_authentication_key(&alice, ED25519_SCHEME, pk, ED25519_SCHEME, pk, test_signature, test_signature); + rotate_authentication_key( + &alice, + ED25519_SCHEME, + pk, + ED25519_SCHEME, + pk, + test_signature, + test_signature + ); } #[test_only] - public fun create_account_from_ed25519_public_key(pk_bytes: vector): signer { + public fun create_account_from_ed25519_public_key( + pk_bytes: vector + ): signer { let pk = ed25519::new_unvalidated_public_key_from_bytes(pk_bytes); let curr_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&pk); let alice_address = from_bcs::to_address(curr_auth_key); @@ -1132,7 +1249,7 @@ module supra_framework::account { let challenge = SignerCapabilityOfferProofChallengeV2 { sequence_number: borrow_global(alice_addr).sequence_number, source_address: alice_addr, - recipient_address: bob_addr, + recipient_address: bob_addr }; let sig = ed25519::sign_struct(&_alice_sk, challenge); @@ -1146,7 +1263,9 @@ module supra_framework::account { } #[test(bob = @0x345)] - public entry fun test_valid_check_signer_capability_and_create_authorized_signer(bob: signer) acquires Account { + public entry fun test_valid_check_signer_capability_and_create_authorized_signer( + bob: signer + ) acquires Account { let (alice_sk, alice_pk) = ed25519::generate_keys(); let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk); let alice = create_account_from_ed25519_public_key(alice_pk_bytes); @@ -1158,7 +1277,7 @@ module supra_framework::account { let challenge = SignerCapabilityOfferProofChallengeV2 { sequence_number: borrow_global(alice_addr).sequence_number, source_address: alice_addr, - recipient_address: bob_addr, + recipient_address: bob_addr }; let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); @@ -1171,7 +1290,12 @@ module supra_framework::account { bob_addr ); - assert!(option::contains(&borrow_global(alice_addr).signer_capability_offer.for, &bob_addr), 0); + assert!( + option::contains( + &borrow_global(alice_addr).signer_capability_offer.for, &bob_addr + ), + 0 + ); let signer = create_authorized_signer(&bob, alice_addr); assert!(signer::address_of(&signer) == signer::address_of(&alice), 0); @@ -1190,7 +1314,7 @@ module supra_framework::account { let challenge = SignerCapabilityOfferProofChallengeV2 { sequence_number: borrow_global(alice_addr).sequence_number, source_address: alice_addr, - recipient_address: bob_addr, + recipient_address: bob_addr }; let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); @@ -1207,12 +1331,10 @@ module supra_framework::account { assert!(get_signer_capability_offer_for(alice_addr) == bob_addr, 0); } - #[test(bob = @0x345, charlie = @0x567)] #[expected_failure(abort_code = 393230, location = Self)] public entry fun test_invalid_check_signer_capability_and_create_authorized_signer( - bob: signer, - charlie: signer + bob: signer, charlie: signer ) acquires Account { let (alice_sk, alice_pk) = ed25519::generate_keys(); let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk); @@ -1225,7 +1347,7 @@ module supra_framework::account { let challenge = SignerCapabilityOfferProofChallengeV2 { sequence_number: borrow_global(alice_addr).sequence_number, source_address: alice_addr, - recipient_address: bob_addr, + recipient_address: bob_addr }; let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); @@ -1239,7 +1361,12 @@ module supra_framework::account { ); let alice_account_resource = borrow_global_mut(alice_addr); - assert!(option::contains(&alice_account_resource.signer_capability_offer.for, &bob_addr), 0); + assert!( + option::contains( + &alice_account_resource.signer_capability_offer.for, &bob_addr + ), + 0 + ); create_authorized_signer(&charlie, alice_addr); } @@ -1257,7 +1384,7 @@ module supra_framework::account { let challenge = SignerCapabilityOfferProofChallengeV2 { sequence_number: borrow_global(alice_addr).sequence_number, source_address: alice_addr, - recipient_address: bob_addr, + recipient_address: bob_addr }; let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); @@ -1274,7 +1401,9 @@ module supra_framework::account { #[test(bob = @0x345, charlie = @0x567)] #[expected_failure(abort_code = 393230, location = Self)] - public entry fun test_invalid_revoke_signer_capability(bob: signer, charlie: signer) acquires Account { + public entry fun test_invalid_revoke_signer_capability( + bob: signer, charlie: signer + ) acquires Account { let (alice_sk, alice_pk) = ed25519::generate_keys(); let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk); let alice = create_account_from_ed25519_public_key(alice_pk_bytes); @@ -1290,7 +1419,7 @@ module supra_framework::account { let challenge = SignerCapabilityOfferProofChallengeV2 { sequence_number: alice_account_resource.sequence_number, source_address: alice_addr, - recipient_address: bob_addr, + recipient_address: bob_addr }; let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); offer_signer_capability( @@ -1307,7 +1436,9 @@ module supra_framework::account { // Tests for offering rotation capabilities // #[test(bob = @0x345, framework = @supra_framework)] - public entry fun test_valid_offer_rotation_capability(bob: signer, framework: signer) acquires Account { + public entry fun test_valid_offer_rotation_capability( + bob: signer, framework: signer + ) acquires Account { chain_id::initialize_for_test(&framework, 4); let (alice_sk, alice_pk) = ed25519::generate_keys(); let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk); @@ -1321,10 +1452,11 @@ module supra_framework::account { chain_id: chain_id::get(), sequence_number: get_sequence_number(alice_addr), source_address: alice_addr, - recipient_address: bob_addr, + recipient_address: bob_addr }; - let alice_rotation_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); + let alice_rotation_capability_offer_sig = + ed25519::sign_struct(&alice_sk, challenge); offer_rotation_capability( &alice, @@ -1335,12 +1467,16 @@ module supra_framework::account { ); let alice_resource = borrow_global_mut(signer::address_of(&alice)); - assert!(option::contains(&alice_resource.rotation_capability_offer.for, &bob_addr), 0); + assert!( + option::contains(&alice_resource.rotation_capability_offer.for, &bob_addr), 0 + ); } #[test(bob = @0x345, framework = @supra_framework)] #[expected_failure(abort_code = 65544, location = Self)] - public entry fun test_invalid_offer_rotation_capability(bob: signer, framework: signer) acquires Account { + public entry fun test_invalid_offer_rotation_capability( + bob: signer, framework: signer + ) acquires Account { chain_id::initialize_for_test(&framework, 4); let (alice_sk, alice_pk) = ed25519::generate_keys(); let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk); @@ -1355,10 +1491,11 @@ module supra_framework::account { // Intentionally make the signature invalid. sequence_number: 2, source_address: alice_addr, - recipient_address: bob_addr, + recipient_address: bob_addr }; - let alice_rotation_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); + let alice_rotation_capability_offer_sig = + ed25519::sign_struct(&alice_sk, challenge); offer_rotation_capability( &alice, @@ -1370,7 +1507,9 @@ module supra_framework::account { } #[test(bob = @0x345, framework = @supra_framework)] - public entry fun test_valid_revoke_rotation_capability(bob: signer, framework: signer) acquires Account { + public entry fun test_valid_revoke_rotation_capability( + bob: signer, framework: signer + ) acquires Account { chain_id::initialize_for_test(&framework, 4); let (alice_sk, alice_pk) = ed25519::generate_keys(); let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk); @@ -1384,10 +1523,11 @@ module supra_framework::account { chain_id: chain_id::get(), sequence_number: get_sequence_number(alice_addr), source_address: alice_addr, - recipient_address: bob_addr, + recipient_address: bob_addr }; - let alice_rotation_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); + let alice_rotation_capability_offer_sig = + ed25519::sign_struct(&alice_sk, challenge); offer_rotation_capability( &alice, @@ -1402,9 +1542,7 @@ module supra_framework::account { #[test(bob = @0x345, charlie = @0x567, framework = @supra_framework)] #[expected_failure(abort_code = 393234, location = Self)] public entry fun test_invalid_revoke_rotation_capability( - bob: signer, - charlie: signer, - framework: signer + bob: signer, charlie: signer, framework: signer ) acquires Account { chain_id::initialize_for_test(&framework, 4); let (alice_sk, alice_pk) = ed25519::generate_keys(); @@ -1420,10 +1558,11 @@ module supra_framework::account { chain_id: chain_id::get(), sequence_number: get_sequence_number(alice_addr), source_address: alice_addr, - recipient_address: bob_addr, + recipient_address: bob_addr }; - let alice_rotation_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge); + let alice_rotation_capability_offer_sig = + ed25519::sign_struct(&alice_sk, challenge); offer_rotation_capability( &alice, @@ -1446,20 +1585,28 @@ module supra_framework::account { initialize(&account); let (curr_sk, curr_pk) = multi_ed25519::generate_keys(2, 3); let curr_pk_unvalidated = multi_ed25519::public_key_to_unvalidated(&curr_pk); - let curr_auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&curr_pk_unvalidated); + let curr_auth_key = + multi_ed25519::unvalidated_public_key_to_authentication_key( + &curr_pk_unvalidated + ); let alice_addr = from_bcs::to_address(curr_auth_key); let alice = create_account_unchecked(alice_addr); let (new_sk, new_pk) = multi_ed25519::generate_keys(4, 5); let new_pk_unvalidated = multi_ed25519::public_key_to_unvalidated(&new_pk); - let new_auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&new_pk_unvalidated); + let new_auth_key = + multi_ed25519::unvalidated_public_key_to_authentication_key( + &new_pk_unvalidated + ); let new_address = from_bcs::to_address(new_auth_key); let challenge = RotationProofChallenge { sequence_number: borrow_global(alice_addr).sequence_number, originator: alice_addr, current_auth_key: alice_addr, - new_public_key: multi_ed25519::unvalidated_public_key_to_bytes(&new_pk_unvalidated), + new_public_key: multi_ed25519::unvalidated_public_key_to_bytes( + &new_pk_unvalidated + ) }; let from_sig = multi_ed25519::sign_struct(&curr_sk, challenge); @@ -1472,9 +1619,10 @@ module supra_framework::account { MULTI_ED25519_SCHEME, multi_ed25519::unvalidated_public_key_to_bytes(&new_pk_unvalidated), multi_ed25519::signature_to_bytes(&from_sig), - multi_ed25519::signature_to_bytes(&to_sig), + multi_ed25519::signature_to_bytes(&to_sig) ); - let address_map = &mut borrow_global_mut(@supra_framework).address_map; + let address_map = + &mut borrow_global_mut(@supra_framework).address_map; let expected_originating_address = table::borrow(address_map, new_address); assert!(*expected_originating_address == alice_addr, 0); assert!(borrow_global(alice_addr).authentication_key == new_auth_key, 0); @@ -1488,7 +1636,10 @@ module supra_framework::account { let (curr_sk, curr_pk) = multi_ed25519::generate_keys(2, 3); let curr_pk_unvalidated = multi_ed25519::public_key_to_unvalidated(&curr_pk); - let curr_auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&curr_pk_unvalidated); + let curr_auth_key = + multi_ed25519::unvalidated_public_key_to_authentication_key( + &curr_pk_unvalidated + ); let alice_addr = from_bcs::to_address(curr_auth_key); let alice = create_account_unchecked(alice_addr); @@ -1496,14 +1647,15 @@ module supra_framework::account { let (new_sk, new_pk) = ed25519::generate_keys(); let new_pk_unvalidated = ed25519::public_key_to_unvalidated(&new_pk); - let new_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&new_pk_unvalidated); + let new_auth_key = + ed25519::unvalidated_public_key_to_authentication_key(&new_pk_unvalidated); let new_addr = from_bcs::to_address(new_auth_key); let challenge = RotationProofChallenge { sequence_number: account_resource.sequence_number, originator: alice_addr, current_auth_key: alice_addr, - new_public_key: ed25519::unvalidated_public_key_to_bytes(&new_pk_unvalidated), + new_public_key: ed25519::unvalidated_public_key_to_bytes(&new_pk_unvalidated) }; let from_sig = multi_ed25519::sign_struct(&curr_sk, challenge); @@ -1516,16 +1668,16 @@ module supra_framework::account { ED25519_SCHEME, ed25519::unvalidated_public_key_to_bytes(&new_pk_unvalidated), multi_ed25519::signature_to_bytes(&from_sig), - ed25519::signature_to_bytes(&to_sig), + ed25519::signature_to_bytes(&to_sig) ); - let address_map = &mut borrow_global_mut(@supra_framework).address_map; + let address_map = + &mut borrow_global_mut(@supra_framework).address_map; let expected_originating_address = table::borrow(address_map, new_addr); assert!(*expected_originating_address == alice_addr, 0); assert!(borrow_global(alice_addr).authentication_key == new_auth_key, 0); } - #[test(account = @supra_framework)] public entry fun test_simple_rotation(account: &signer) acquires Account { initialize(account); @@ -1535,14 +1687,14 @@ module supra_framework::account { let (_new_sk, new_pk) = ed25519::generate_keys(); let new_pk_unvalidated = ed25519::public_key_to_unvalidated(&new_pk); - let new_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&new_pk_unvalidated); + let new_auth_key = + ed25519::unvalidated_public_key_to_authentication_key(&new_pk_unvalidated); let _new_addr = from_bcs::to_address(new_auth_key); rotate_authentication_key_call(&alice, new_auth_key); assert!(borrow_global(alice_addr).authentication_key == new_auth_key, 0); } - #[test(account = @supra_framework)] #[expected_failure(abort_code = 0x20014, location = Self)] public entry fun test_max_guid(account: &signer) acquires Account { @@ -1566,14 +1718,18 @@ module supra_framework::account { register_coin(addr); let eventhandle = &borrow_global(addr).coin_register_events; - let event = CoinRegisterEvent { type_info: type_info::type_of() }; + let event = CoinRegisterEvent { + type_info: type_info::type_of() + }; let events = event::emitted_events_by_handle(eventhandle); assert!(vector::length(&events) == 1, 0); assert!(vector::borrow(&events, 0) == &event, 1); assert!(event::was_event_emitted_by_handle(eventhandle, &event), 2); - let event = CoinRegisterEvent { type_info: type_info::type_of() }; + let event = CoinRegisterEvent { + type_info: type_info::type_of() + }; assert!(!event::was_event_emitted_by_handle(eventhandle, &event), 3); } } diff --git a/aptos-move/framework/supra-framework/sources/account.spec.move b/aptos-move/framework/supra-framework/sources/account.spec.move index f379f6605116e..f8a0b68f913c5 100644 --- a/aptos-move/framework/supra-framework/sources/account.spec.move +++ b/aptos-move/framework/supra-framework/sources/account.spec.move @@ -122,22 +122,24 @@ spec supra_framework::account { spec create_account_if_does_not_exist(account_address: address) { let authentication_key = bcs::to_bytes(account_address); - aborts_if !exists(account_address) && ( - account_address == @vm_reserved - || account_address == @supra_framework - || account_address == @aptos_token - || !(len(authentication_key) == 32) - ); + aborts_if !exists(account_address) + && ( + account_address == @vm_reserved + || account_address == @supra_framework + || account_address == @aptos_token + || !(len(authentication_key) == 32) + ); ensures exists(account_address); } - /// Check if the bytes of the new address is 32. /// The Account does not exist under the new address before creating the account. /// Limit the new account address is not @vm_reserved / @supra_framework / @aptos_toke. spec create_account(new_address: address): signer { - include CreateAccountAbortsIf {addr: new_address}; - aborts_if new_address == @vm_reserved || new_address == @supra_framework || new_address == @aptos_token; + include CreateAccountAbortsIf { addr: new_address }; + aborts_if new_address == @vm_reserved + || new_address == @supra_framework + || new_address == @aptos_token; ensures signer::address_of(result) == new_address; /// [high-level-req-2] ensures exists(new_address); @@ -146,7 +148,7 @@ spec supra_framework::account { /// Check if the bytes of the new address is 32. /// The Account does not exist under the new address before creating the account. spec create_account_unchecked(new_address: address): signer { - include CreateAccountAbortsIf {addr: new_address}; + include CreateAccountAbortsIf { addr: new_address }; ensures signer::address_of(result) == new_address; ensures exists(new_address); } @@ -213,34 +215,56 @@ spec supra_framework::account { ensures account_resource.authentication_key == new_auth_key; } - spec fun spec_assert_valid_rotation_proof_signature_and_get_auth_key(scheme: u8, public_key_bytes: vector, signature: vector, challenge: RotationProofChallenge): vector; + spec fun spec_assert_valid_rotation_proof_signature_and_get_auth_key( + scheme: u8, + public_key_bytes: vector, + signature: vector, + challenge: RotationProofChallenge + ): vector; - spec assert_valid_rotation_proof_signature_and_get_auth_key(scheme: u8, public_key_bytes: vector, signature: vector, challenge: &RotationProofChallenge): vector { + spec assert_valid_rotation_proof_signature_and_get_auth_key( + scheme: u8, + public_key_bytes: vector, + signature: vector, + challenge: &RotationProofChallenge + ): vector { pragma opaque; include AssertValidRotationProofSignatureAndGetAuthKeyAbortsIf; - ensures [abstract] result == spec_assert_valid_rotation_proof_signature_and_get_auth_key(scheme, public_key_bytes, signature, challenge); + ensures [abstract] result + == spec_assert_valid_rotation_proof_signature_and_get_auth_key( + scheme, public_key_bytes, signature, challenge + ); } + spec schema AssertValidRotationProofSignatureAndGetAuthKeyAbortsIf { scheme: u8; public_key_bytes: vector; signature: vector; challenge: RotationProofChallenge; - include scheme == ED25519_SCHEME ==> ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: public_key_bytes }; - include scheme == ED25519_SCHEME ==> ed25519::NewSignatureFromBytesAbortsIf { bytes: signature }; - aborts_if scheme == ED25519_SCHEME && !ed25519::spec_signature_verify_strict_t( - ed25519::Signature { bytes: signature }, - ed25519::UnvalidatedPublicKey { bytes: public_key_bytes }, - challenge - ); - - include scheme == MULTI_ED25519_SCHEME ==> multi_ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: public_key_bytes }; - include scheme == MULTI_ED25519_SCHEME ==> multi_ed25519::NewSignatureFromBytesAbortsIf { bytes: signature }; - aborts_if scheme == MULTI_ED25519_SCHEME && !multi_ed25519::spec_signature_verify_strict_t( - multi_ed25519::Signature { bytes: signature }, - multi_ed25519::UnvalidatedPublicKey { bytes: public_key_bytes }, - challenge - ); + include scheme == ED25519_SCHEME ==> + ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: public_key_bytes }; + include scheme == ED25519_SCHEME ==> + ed25519::NewSignatureFromBytesAbortsIf { bytes: signature }; + aborts_if scheme == ED25519_SCHEME + && !ed25519::spec_signature_verify_strict_t( + ed25519::Signature { bytes: signature }, + ed25519::UnvalidatedPublicKey { bytes: public_key_bytes }, + challenge + ); + + include scheme == MULTI_ED25519_SCHEME ==> + multi_ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { + bytes: public_key_bytes + }; + include scheme == MULTI_ED25519_SCHEME ==> + multi_ed25519::NewSignatureFromBytesAbortsIf { bytes: signature }; + aborts_if scheme == MULTI_ED25519_SCHEME + && !multi_ed25519::spec_signature_verify_strict_t( + multi_ed25519::Signature { bytes: signature }, + multi_ed25519::UnvalidatedPublicKey { bytes: public_key_bytes }, + challenge + ); aborts_if scheme != ED25519_SCHEME && scheme != MULTI_ED25519_SCHEME; } @@ -253,35 +277,51 @@ spec supra_framework::account { to_scheme: u8, to_public_key_bytes: vector, cap_rotate_key: vector, - cap_update_table: vector, + cap_update_table: vector ) { let addr = signer::address_of(account); let account_resource = global(addr); aborts_if !exists(addr); /// [high-level-req-6.1] - include from_scheme == ED25519_SCHEME ==> ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: from_public_key_bytes }; - aborts_if from_scheme == ED25519_SCHEME && ({ - let expected_auth_key = ed25519::spec_public_key_bytes_to_authentication_key(from_public_key_bytes); - account_resource.authentication_key != expected_auth_key - }); - include from_scheme == MULTI_ED25519_SCHEME ==> multi_ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: from_public_key_bytes }; - aborts_if from_scheme == MULTI_ED25519_SCHEME && ({ - let from_auth_key = multi_ed25519::spec_public_key_bytes_to_authentication_key(from_public_key_bytes); - account_resource.authentication_key != from_auth_key - }); + include from_scheme == ED25519_SCHEME ==> + ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { + bytes: from_public_key_bytes + }; + aborts_if from_scheme == ED25519_SCHEME + && ({ + let expected_auth_key = + ed25519::spec_public_key_bytes_to_authentication_key( + from_public_key_bytes + ); + account_resource.authentication_key != expected_auth_key + }); + include from_scheme == MULTI_ED25519_SCHEME ==> + multi_ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { + bytes: from_public_key_bytes + }; + aborts_if from_scheme == MULTI_ED25519_SCHEME + && ({ + let from_auth_key = + multi_ed25519::spec_public_key_bytes_to_authentication_key( + from_public_key_bytes + ); + account_resource.authentication_key != from_auth_key + }); /// [high-level-req-5.1] aborts_if from_scheme != ED25519_SCHEME && from_scheme != MULTI_ED25519_SCHEME; - let curr_auth_key = from_bcs::deserialize
(account_resource.authentication_key); + let curr_auth_key = from_bcs::deserialize
( + account_resource.authentication_key + ); aborts_if !from_bcs::deserializable
(account_resource.authentication_key); let challenge = RotationProofChallenge { sequence_number: account_resource.sequence_number, originator: addr, current_auth_key: curr_auth_key, - new_public_key: to_public_key_bytes, + new_public_key: to_public_key_bytes }; /// [high-level-req-9.1] @@ -289,35 +329,36 @@ spec supra_framework::account { scheme: from_scheme, public_key_bytes: from_public_key_bytes, signature: cap_rotate_key, - challenge, + challenge }; include AssertValidRotationProofSignatureAndGetAuthKeyAbortsIf { scheme: to_scheme, public_key_bytes: to_public_key_bytes, signature: cap_update_table, - challenge, + challenge }; // Verify all properties in update_auth_key_and_originating_address_table let originating_addr = addr; - let new_auth_key_vector = spec_assert_valid_rotation_proof_signature_and_get_auth_key(to_scheme, to_public_key_bytes, cap_update_table, challenge); + let new_auth_key_vector = spec_assert_valid_rotation_proof_signature_and_get_auth_key( + to_scheme, to_public_key_bytes, cap_update_table, challenge + ); let address_map = global(@supra_framework).address_map; let new_auth_key = from_bcs::deserialize
(new_auth_key_vector); aborts_if !exists(@supra_framework); aborts_if !from_bcs::deserializable
(account_resource.authentication_key); - aborts_if table::spec_contains(address_map, curr_auth_key) && - table::spec_get(address_map, curr_auth_key) != originating_addr; + aborts_if table::spec_contains(address_map, curr_auth_key) + && table::spec_get(address_map, curr_auth_key) != originating_addr; aborts_if !from_bcs::deserializable
(new_auth_key_vector); - aborts_if curr_auth_key != new_auth_key && table::spec_contains(address_map, new_auth_key); + aborts_if curr_auth_key != new_auth_key + && table::spec_contains(address_map, new_auth_key); - include UpdateAuthKeyAndOriginatingAddressTableAbortsIf { - originating_addr: addr, - }; + include UpdateAuthKeyAndOriginatingAddressTableAbortsIf { originating_addr: addr }; let post auth_key = global(addr).authentication_key; ensures auth_key == new_auth_key_vector; @@ -334,41 +375,53 @@ spec supra_framework::account { aborts_if !exists(rotation_cap_offerer_address); let delegate_address = signer::address_of(delegate_signer); let offerer_account_resource = global(rotation_cap_offerer_address); - aborts_if !from_bcs::deserializable
(offerer_account_resource.authentication_key); - let curr_auth_key = from_bcs::deserialize
(offerer_account_resource.authentication_key); + aborts_if !from_bcs::deserializable
( + offerer_account_resource.authentication_key + ); + let curr_auth_key = from_bcs::deserialize
( + offerer_account_resource.authentication_key + ); aborts_if !exists(delegate_address); let challenge = RotationProofChallenge { sequence_number: global(delegate_address).sequence_number, originator: rotation_cap_offerer_address, current_auth_key: curr_auth_key, - new_public_key: new_public_key_bytes, + new_public_key: new_public_key_bytes }; /// [high-level-req-6.2] - aborts_if !option::spec_contains(offerer_account_resource.rotation_capability_offer.for, delegate_address); + aborts_if !option::spec_contains( + offerer_account_resource.rotation_capability_offer.for, delegate_address + ); /// [high-level-req-9.1] include AssertValidRotationProofSignatureAndGetAuthKeyAbortsIf { scheme: new_scheme, public_key_bytes: new_public_key_bytes, signature: cap_update_table, - challenge, + challenge }; - let new_auth_key_vector = spec_assert_valid_rotation_proof_signature_and_get_auth_key(new_scheme, new_public_key_bytes, cap_update_table, challenge); + let new_auth_key_vector = spec_assert_valid_rotation_proof_signature_and_get_auth_key( + new_scheme, new_public_key_bytes, cap_update_table, challenge + ); let address_map = global(@supra_framework).address_map; // Verify all properties in update_auth_key_and_originating_address_table aborts_if !exists(@supra_framework); - aborts_if !from_bcs::deserializable
(offerer_account_resource.authentication_key); - aborts_if table::spec_contains(address_map, curr_auth_key) && - table::spec_get(address_map, curr_auth_key) != rotation_cap_offerer_address; + aborts_if !from_bcs::deserializable
( + offerer_account_resource.authentication_key + ); + aborts_if table::spec_contains(address_map, curr_auth_key) + && table::spec_get(address_map, curr_auth_key) + != rotation_cap_offerer_address; aborts_if !from_bcs::deserializable
(new_auth_key_vector); let new_auth_key = from_bcs::deserialize
(new_auth_key_vector); - aborts_if curr_auth_key != new_auth_key && table::spec_contains(address_map, new_auth_key); + aborts_if curr_auth_key != new_auth_key + && table::spec_contains(address_map, new_auth_key); include UpdateAuthKeyAndOriginatingAddressTableAbortsIf { originating_addr: rotation_cap_offerer_address, - account_resource: offerer_account_resource, + account_resource: offerer_account_resource }; let post auth_key = global(rotation_cap_offerer_address).authentication_key; @@ -380,7 +433,7 @@ spec supra_framework::account { rotation_capability_sig_bytes: vector, account_scheme: u8, account_public_key_bytes: vector, - recipient_address: address, + recipient_address: address ) { let source_address = signer::address_of(account); let account_resource = global(source_address); @@ -388,39 +441,60 @@ spec supra_framework::account { chain_id: global(@supra_framework).id, sequence_number: account_resource.sequence_number, source_address, - recipient_address, + recipient_address }; aborts_if !exists(@supra_framework); aborts_if !exists(recipient_address); aborts_if !exists(source_address); - include account_scheme == ED25519_SCHEME ==> ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: account_public_key_bytes }; - aborts_if account_scheme == ED25519_SCHEME && ({ - let expected_auth_key = ed25519::spec_public_key_bytes_to_authentication_key(account_public_key_bytes); - account_resource.authentication_key != expected_auth_key - }); - include account_scheme == ED25519_SCHEME ==> ed25519::NewSignatureFromBytesAbortsIf { bytes: rotation_capability_sig_bytes }; - aborts_if account_scheme == ED25519_SCHEME && !ed25519::spec_signature_verify_strict_t( - ed25519::Signature { bytes: rotation_capability_sig_bytes }, - ed25519::UnvalidatedPublicKey { bytes: account_public_key_bytes }, - proof_challenge - ); - - include account_scheme == MULTI_ED25519_SCHEME ==> multi_ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: account_public_key_bytes }; - aborts_if account_scheme == MULTI_ED25519_SCHEME && ({ - let expected_auth_key = multi_ed25519::spec_public_key_bytes_to_authentication_key(account_public_key_bytes); - account_resource.authentication_key != expected_auth_key - }); - include account_scheme == MULTI_ED25519_SCHEME ==> multi_ed25519::NewSignatureFromBytesAbortsIf { bytes: rotation_capability_sig_bytes }; - aborts_if account_scheme == MULTI_ED25519_SCHEME && !multi_ed25519::spec_signature_verify_strict_t( - multi_ed25519::Signature { bytes: rotation_capability_sig_bytes }, - multi_ed25519::UnvalidatedPublicKey { bytes: account_public_key_bytes }, - proof_challenge - ); + include account_scheme == ED25519_SCHEME ==> + ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { + bytes: account_public_key_bytes + }; + aborts_if account_scheme == ED25519_SCHEME + && ({ + let expected_auth_key = + ed25519::spec_public_key_bytes_to_authentication_key( + account_public_key_bytes + ); + account_resource.authentication_key != expected_auth_key + }); + include account_scheme == ED25519_SCHEME ==> + ed25519::NewSignatureFromBytesAbortsIf { bytes: rotation_capability_sig_bytes }; + aborts_if account_scheme == ED25519_SCHEME + && !ed25519::spec_signature_verify_strict_t( + ed25519::Signature { bytes: rotation_capability_sig_bytes }, + ed25519::UnvalidatedPublicKey { bytes: account_public_key_bytes }, + proof_challenge + ); + + include account_scheme == MULTI_ED25519_SCHEME ==> + multi_ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { + bytes: account_public_key_bytes + }; + aborts_if account_scheme == MULTI_ED25519_SCHEME + && ({ + let expected_auth_key = + multi_ed25519::spec_public_key_bytes_to_authentication_key( + account_public_key_bytes + ); + account_resource.authentication_key != expected_auth_key + }); + include account_scheme == MULTI_ED25519_SCHEME ==> + multi_ed25519::NewSignatureFromBytesAbortsIf { + bytes: rotation_capability_sig_bytes + }; + aborts_if account_scheme == MULTI_ED25519_SCHEME + && !multi_ed25519::spec_signature_verify_strict_t( + multi_ed25519::Signature { bytes: rotation_capability_sig_bytes }, + multi_ed25519::UnvalidatedPublicKey { bytes: account_public_key_bytes }, + proof_challenge + ); /// [high-level-req-5.2] - aborts_if account_scheme != ED25519_SCHEME && account_scheme != MULTI_ED25519_SCHEME; + aborts_if account_scheme != ED25519_SCHEME + && account_scheme != MULTI_ED25519_SCHEME; /// [high-level-req-7.1] modifies global(source_address); @@ -442,38 +516,59 @@ spec supra_framework::account { let proof_challenge = SignerCapabilityOfferProofChallengeV2 { sequence_number: account_resource.sequence_number, source_address, - recipient_address, + recipient_address }; aborts_if !exists(recipient_address); aborts_if !exists(source_address); - include account_scheme == ED25519_SCHEME ==> ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: account_public_key_bytes }; - aborts_if account_scheme == ED25519_SCHEME && ({ - let expected_auth_key = ed25519::spec_public_key_bytes_to_authentication_key(account_public_key_bytes); - account_resource.authentication_key != expected_auth_key - }); - include account_scheme == ED25519_SCHEME ==> ed25519::NewSignatureFromBytesAbortsIf { bytes: signer_capability_sig_bytes }; - aborts_if account_scheme == ED25519_SCHEME && !ed25519::spec_signature_verify_strict_t( - ed25519::Signature { bytes: signer_capability_sig_bytes }, - ed25519::UnvalidatedPublicKey { bytes: account_public_key_bytes }, - proof_challenge - ); - - include account_scheme == MULTI_ED25519_SCHEME ==> multi_ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: account_public_key_bytes }; - aborts_if account_scheme == MULTI_ED25519_SCHEME && ({ - let expected_auth_key = multi_ed25519::spec_public_key_bytes_to_authentication_key(account_public_key_bytes); - account_resource.authentication_key != expected_auth_key - }); - include account_scheme == MULTI_ED25519_SCHEME ==> multi_ed25519::NewSignatureFromBytesAbortsIf { bytes: signer_capability_sig_bytes }; - aborts_if account_scheme == MULTI_ED25519_SCHEME && !multi_ed25519::spec_signature_verify_strict_t( - multi_ed25519::Signature { bytes: signer_capability_sig_bytes }, - multi_ed25519::UnvalidatedPublicKey { bytes: account_public_key_bytes }, - proof_challenge - ); + include account_scheme == ED25519_SCHEME ==> + ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { + bytes: account_public_key_bytes + }; + aborts_if account_scheme == ED25519_SCHEME + && ({ + let expected_auth_key = + ed25519::spec_public_key_bytes_to_authentication_key( + account_public_key_bytes + ); + account_resource.authentication_key != expected_auth_key + }); + include account_scheme == ED25519_SCHEME ==> + ed25519::NewSignatureFromBytesAbortsIf { bytes: signer_capability_sig_bytes }; + aborts_if account_scheme == ED25519_SCHEME + && !ed25519::spec_signature_verify_strict_t( + ed25519::Signature { bytes: signer_capability_sig_bytes }, + ed25519::UnvalidatedPublicKey { bytes: account_public_key_bytes }, + proof_challenge + ); + + include account_scheme == MULTI_ED25519_SCHEME ==> + multi_ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { + bytes: account_public_key_bytes + }; + aborts_if account_scheme == MULTI_ED25519_SCHEME + && ({ + let expected_auth_key = + multi_ed25519::spec_public_key_bytes_to_authentication_key( + account_public_key_bytes + ); + account_resource.authentication_key != expected_auth_key + }); + include account_scheme == MULTI_ED25519_SCHEME ==> + multi_ed25519::NewSignatureFromBytesAbortsIf { + bytes: signer_capability_sig_bytes + }; + aborts_if account_scheme == MULTI_ED25519_SCHEME + && !multi_ed25519::spec_signature_verify_strict_t( + multi_ed25519::Signature { bytes: signer_capability_sig_bytes }, + multi_ed25519::UnvalidatedPublicKey { bytes: account_public_key_bytes }, + proof_challenge + ); /// [high-level-req-5.3] - aborts_if account_scheme != ED25519_SCHEME && account_scheme != MULTI_ED25519_SCHEME; + aborts_if account_scheme != ED25519_SCHEME + && account_scheme != MULTI_ED25519_SCHEME; /// [high-level-req-7.2] modifies global(source_address); @@ -508,7 +603,9 @@ spec supra_framework::account { let addr = signer::address_of(account); let account_resource = global(addr); aborts_if !exists(addr); - aborts_if !option::spec_contains(account_resource.signer_capability_offer.for,to_be_revoked_address); + aborts_if !option::spec_contains( + account_resource.signer_capability_offer.for, to_be_revoked_address + ); modifies global(addr); ensures exists(to_be_revoked_address); } @@ -526,7 +623,9 @@ spec supra_framework::account { let addr = signer::address_of(account); let account_resource = global(addr); aborts_if !exists(addr); - aborts_if !option::spec_contains(account_resource.rotation_capability_offer.for,to_be_revoked_address); + aborts_if !option::spec_contains( + account_resource.rotation_capability_offer.for, to_be_revoked_address + ); modifies global(addr); ensures exists(to_be_revoked_address); let post offer_for = global(addr).rotation_capability_offer.for; @@ -548,10 +647,7 @@ spec supra_framework::account { /// The value of signer_capability_offer.for of Account resource under the signer is offerer_address. spec create_authorized_signer(account: &signer, offerer_address: address): signer { /// [high-level-req-8] - include AccountContainsAddr{ - account, - address: offerer_address, - }; + include AccountContainsAddr { account, address: offerer_address }; modifies global(offerer_address); ensures exists(offerer_address); ensures signer::address_of(result) == offerer_address; @@ -564,7 +660,9 @@ spec supra_framework::account { let account_resource = global(address); aborts_if !exists(address); /// [create_signer::high-level-spec-3] - aborts_if !option::spec_contains(account_resource.signer_capability_offer.for,addr); + aborts_if !option::spec_contains( + account_resource.signer_capability_offer.for, addr + ); } /// The Account existed under the signer @@ -584,8 +682,10 @@ spec supra_framework::account { let resource_addr = spec_create_resource_address(source_addr, seed); aborts_if len(ZERO_AUTH_KEY) != 32; - include exists_at(resource_addr) ==> CreateResourceAccountAbortsIf; - include !exists_at(resource_addr) ==> CreateAccountAbortsIf {addr: resource_addr}; + include exists_at(resource_addr) ==> + CreateResourceAccountAbortsIf; + include !exists_at(resource_addr) ==> + CreateAccountAbortsIf { addr: resource_addr }; ensures signer::address_of(result_1) == resource_addr; let post offer_for = global(resource_addr).signer_capability_offer.for; @@ -598,34 +698,33 @@ spec supra_framework::account { /// The system reserved addresses is @0x1 / @0x2 / @0x3 / @0x4 / @0x5 / @0x6 / @0x7 / @0x8 / @0x9 / @0xa. spec create_framework_reserved_account(addr: address): (signer, SignerCapability) { aborts_if spec_is_framework_address(addr); - include CreateAccountAbortsIf {addr}; + include CreateAccountAbortsIf { addr }; ensures signer::address_of(result_1) == addr; ensures result_2 == SignerCapability { account: addr }; } - spec fun spec_is_framework_address(addr: address): bool{ - addr != @0x1 && - addr != @0x2 && - addr != @0x3 && - addr != @0x4 && - addr != @0x5 && - addr != @0x6 && - addr != @0x7 && - addr != @0x8 && - addr != @0x9 && - addr != @0xa + spec fun spec_is_framework_address(addr: address): bool { + addr != @0x1 + && addr != @0x2 + && addr != @0x3 + && addr != @0x4 + && addr != @0x5 + && addr != @0x6 + && addr != @0x7 + && addr != @0x8 + && addr != @0x9 + && addr != @0xa } /// The Account existed under the signer. /// The guid_creation_num of the ccount resource is up to MAX_U64. spec create_guid(account_signer: &signer): guid::GUID { let addr = signer::address_of(account_signer); - include NewEventHandleAbortsIf { - account: account_signer, - }; + include NewEventHandleAbortsIf { account: account_signer }; modifies global(addr); /// [high-level-req-11] - ensures global(addr).guid_creation_num == old(global(addr).guid_creation_num) + 1; + ensures global(addr).guid_creation_num + == old(global(addr).guid_creation_num) + 1; } /// The Account existed under the signer. @@ -633,6 +732,7 @@ spec supra_framework::account { spec new_event_handle(account: &signer): EventHandle { include NewEventHandleAbortsIf; } + spec schema NewEventHandleAbortsIf { account: &signer; let addr = signer::address_of(account); @@ -663,26 +763,33 @@ spec supra_framework::account { spec update_auth_key_and_originating_address_table( originating_addr: address, account_resource: &mut Account, - new_auth_key_vector: vector, + new_auth_key_vector: vector ) { modifies global(@supra_framework); include UpdateAuthKeyAndOriginatingAddressTableAbortsIf; } + spec schema UpdateAuthKeyAndOriginatingAddressTableAbortsIf { originating_addr: address; account_resource: Account; new_auth_key_vector: vector; let address_map = global(@supra_framework).address_map; - let curr_auth_key = from_bcs::deserialize
(account_resource.authentication_key); + let curr_auth_key = from_bcs::deserialize
( + account_resource.authentication_key + ); let new_auth_key = from_bcs::deserialize
(new_auth_key_vector); aborts_if !exists(@supra_framework); aborts_if !from_bcs::deserializable
(account_resource.authentication_key); - aborts_if table::spec_contains(address_map, curr_auth_key) && - table::spec_get(address_map, curr_auth_key) != originating_addr; + aborts_if table::spec_contains(address_map, curr_auth_key) + && table::spec_get(address_map, curr_auth_key) != originating_addr; aborts_if !from_bcs::deserializable
(new_auth_key_vector); - aborts_if curr_auth_key != new_auth_key && table::spec_contains(address_map, new_auth_key); + aborts_if curr_auth_key != new_auth_key + && table::spec_contains(address_map, new_auth_key); - ensures table::spec_contains(global(@supra_framework).address_map, from_bcs::deserialize
(new_auth_key_vector)); + ensures table::spec_contains( + global(@supra_framework).address_map, + from_bcs::deserialize
(new_auth_key_vector) + ); } spec verify_signed_message( @@ -690,7 +797,7 @@ spec supra_framework::account { account_scheme: u8, account_public_key: vector, signed_message_bytes: vector, - message: T, + message: T ) { pragma aborts_if_is_partial; @@ -698,19 +805,32 @@ spec supra_framework::account { let account_resource = global(account); aborts_if !exists(account); - include account_scheme == ED25519_SCHEME ==> ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: account_public_key }; - aborts_if account_scheme == ED25519_SCHEME && ({ - let expected_auth_key = ed25519::spec_public_key_bytes_to_authentication_key(account_public_key); - account_resource.authentication_key != expected_auth_key - }); - - include account_scheme == MULTI_ED25519_SCHEME ==> multi_ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: account_public_key }; - aborts_if account_scheme == MULTI_ED25519_SCHEME && ({ - let expected_auth_key = multi_ed25519::spec_public_key_bytes_to_authentication_key(account_public_key); - account_resource.authentication_key != expected_auth_key - }); - - include account_scheme == ED25519_SCHEME ==> ed25519::NewSignatureFromBytesAbortsIf { bytes: signed_message_bytes }; + include account_scheme == ED25519_SCHEME ==> + ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: account_public_key }; + aborts_if account_scheme == ED25519_SCHEME + && ({ + let expected_auth_key = + ed25519::spec_public_key_bytes_to_authentication_key( + account_public_key + ); + account_resource.authentication_key != expected_auth_key + }); + + include account_scheme == MULTI_ED25519_SCHEME ==> + multi_ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { + bytes: account_public_key + }; + aborts_if account_scheme == MULTI_ED25519_SCHEME + && ({ + let expected_auth_key = + multi_ed25519::spec_public_key_bytes_to_authentication_key( + account_public_key + ); + account_resource.authentication_key != expected_auth_key + }); + + include account_scheme == ED25519_SCHEME ==> + ed25519::NewSignatureFromBytesAbortsIf { bytes: signed_message_bytes }; // TODO: compiler error with message T // aborts_if account_scheme == ED25519_SCHEME && !ed25519::spec_signature_verify_strict_t( // ed25519::Signature { bytes: signed_message_bytes }, @@ -718,7 +838,8 @@ spec supra_framework::account { // message // ); - include account_scheme == MULTI_ED25519_SCHEME ==> multi_ed25519::NewSignatureFromBytesAbortsIf { bytes: signed_message_bytes }; + include account_scheme == MULTI_ED25519_SCHEME ==> + multi_ed25519::NewSignatureFromBytesAbortsIf { bytes: signed_message_bytes }; // TODO: compiler error with message T // aborts_if account_scheme == MULTI_ED25519_SCHEME && !multi_ed25519::spec_signature_verify_strict_t( // multi_ed25519::Signature { bytes: signed_message_bytes }, @@ -726,6 +847,7 @@ spec supra_framework::account { // message // ); - aborts_if account_scheme != ED25519_SCHEME && account_scheme != MULTI_ED25519_SCHEME; + aborts_if account_scheme != ED25519_SCHEME + && account_scheme != MULTI_ED25519_SCHEME; } } diff --git a/aptos-move/framework/supra-framework/sources/aggregator/aggregator.move b/aptos-move/framework/supra-framework/sources/aggregator/aggregator.move index 4c448d335b48a..337d9278ab4ad 100644 --- a/aptos-move/framework/supra-framework/sources/aggregator/aggregator.move +++ b/aptos-move/framework/supra-framework/sources/aggregator/aggregator.move @@ -26,7 +26,7 @@ module supra_framework::aggregator { struct Aggregator has store { handle: address, key: address, - limit: u128, + limit: u128 } /// Returns `limit` exceeding which aggregator overflows. diff --git a/aptos-move/framework/supra-framework/sources/aggregator/aggregator.spec.move b/aptos-move/framework/supra-framework/sources/aggregator/aggregator.spec.move index 1f9f11b0788cb..334940c5abcb9 100644 --- a/aptos-move/framework/supra-framework/sources/aggregator/aggregator.spec.move +++ b/aptos-move/framework/supra-framework/sources/aggregator/aggregator.spec.move @@ -28,20 +28,27 @@ spec supra_framework::aggregator { spec add(aggregator: &mut Aggregator, value: u128) { pragma opaque; - aborts_if spec_aggregator_get_val(aggregator) + value > spec_get_limit(aggregator); + aborts_if spec_aggregator_get_val(aggregator) + value + > spec_get_limit(aggregator); /// [high-level-req-2] aborts_if spec_aggregator_get_val(aggregator) + value > MAX_U128; ensures spec_get_limit(aggregator) == spec_get_limit(old(aggregator)); - ensures aggregator == spec_aggregator_set_val(old(aggregator), - spec_aggregator_get_val(old(aggregator)) + value); + ensures aggregator + == spec_aggregator_set_val( + old(aggregator), + spec_aggregator_get_val(old(aggregator)) + value + ); } spec sub(aggregator: &mut Aggregator, value: u128) { pragma opaque; aborts_if spec_aggregator_get_val(aggregator) < value; ensures spec_get_limit(aggregator) == spec_get_limit(old(aggregator)); - ensures aggregator == spec_aggregator_set_val(old(aggregator), - spec_aggregator_get_val(old(aggregator)) - value); + ensures aggregator + == spec_aggregator_set_val( + old(aggregator), + spec_aggregator_get_val(old(aggregator)) - value + ); } spec read(aggregator: &Aggregator): u128 { @@ -66,9 +73,14 @@ spec supra_framework::aggregator { } spec native fun spec_read(aggregator: Aggregator): u128; + spec native fun spec_get_limit(a: Aggregator): u128; + spec native fun spec_get_handle(a: Aggregator): u128; + spec native fun spec_get_key(a: Aggregator): u128; + spec native fun spec_aggregator_set_val(a: Aggregator, v: u128): Aggregator; + spec native fun spec_aggregator_get_val(a: Aggregator): u128; } diff --git a/aptos-move/framework/supra-framework/sources/aggregator/aggregator_factory.move b/aptos-move/framework/supra-framework/sources/aggregator/aggregator_factory.move index 1f32b91bb3490..350f7f4f12253 100644 --- a/aptos-move/framework/supra-framework/sources/aggregator/aggregator_factory.move +++ b/aptos-move/framework/supra-framework/sources/aggregator/aggregator_factory.move @@ -20,20 +20,22 @@ module supra_framework::aggregator_factory { /// system and who can create them. At the moment, only Supra Framework (0x1) /// account can. struct AggregatorFactory has key { - phantom_table: Table, + phantom_table: Table } /// Creates a new factory for aggregators. Can only be called during genesis. - public(friend) fun initialize_aggregator_factory(supra_framework: &signer) { + public(friend) fun initialize_aggregator_factory( + supra_framework: &signer + ) { system_addresses::assert_supra_framework(supra_framework); - let aggregator_factory = AggregatorFactory { - phantom_table: table::new() - }; + let aggregator_factory = AggregatorFactory { phantom_table: table::new() }; move_to(supra_framework, aggregator_factory); } /// Creates a new aggregator instance which overflows on exceeding a `limit`. - public(friend) fun create_aggregator_internal(limit: u128): Aggregator acquires AggregatorFactory { + public(friend) fun create_aggregator_internal( + limit: u128 + ): Aggregator acquires AggregatorFactory { assert!( exists(@supra_framework), error::not_found(EAGGREGATOR_FACTORY_NOT_FOUND) @@ -52,10 +54,14 @@ module supra_framework::aggregator_factory { } /// Returns a new aggregator. - native fun new_aggregator(aggregator_factory: &mut AggregatorFactory, limit: u128): Aggregator; + native fun new_aggregator( + aggregator_factory: &mut AggregatorFactory, limit: u128 + ): Aggregator; #[test_only] - public fun initialize_aggregator_factory_for_test(supra_framework: &signer) { + public fun initialize_aggregator_factory_for_test( + supra_framework: &signer + ) { initialize_aggregator_factory(supra_framework); } diff --git a/aptos-move/framework/supra-framework/sources/aggregator/aggregator_factory.spec.move b/aptos-move/framework/supra-framework/sources/aggregator/aggregator_factory.spec.move index a2fa94ca4fcac..a0e3c31861532 100644 --- a/aptos-move/framework/supra-framework/sources/aggregator/aggregator_factory.spec.move +++ b/aptos-move/framework/supra-framework/sources/aggregator/aggregator_factory.spec.move @@ -60,6 +60,7 @@ spec supra_framework::aggregator_factory { ensures aggregator::spec_get_limit(result) == limit; ensures aggregator::spec_aggregator_get_val(result) == 0; } + spec schema CreateAggregatorInternalAbortsIf { aborts_if !exists(@supra_framework); } diff --git a/aptos-move/framework/supra-framework/sources/aggregator/optional_aggregator.move b/aptos-move/framework/supra-framework/sources/aggregator/optional_aggregator.move index 9e5becb000969..a2d68ec5162e1 100644 --- a/aptos-move/framework/supra-framework/sources/aggregator/optional_aggregator.move +++ b/aptos-move/framework/supra-framework/sources/aggregator/optional_aggregator.move @@ -19,15 +19,12 @@ module supra_framework::optional_aggregator { /// Wrapper around integer with a custom overflow limit. Supports add, subtract and read just like `Aggregator`. struct Integer has store { value: u128, - limit: u128, + limit: u128 } /// Creates a new integer which overflows on exceeding a `limit`. fun new_integer(limit: u128): Integer { - Integer { - value: 0, - limit, - } + Integer { value: 0, limit } } /// Adds `value` to integer. Aborts on overflowing the limit. @@ -65,20 +62,22 @@ module supra_framework::optional_aggregator { // Parallelizable. aggregator: Option, // Non-parallelizable. - integer: Option, + integer: Option } /// Creates a new optional aggregator. public(friend) fun new(limit: u128, parallelizable: bool): OptionalAggregator { if (parallelizable) { OptionalAggregator { - aggregator: option::some(aggregator_factory::create_aggregator_internal(limit)), - integer: option::none(), + aggregator: option::some( + aggregator_factory::create_aggregator_internal(limit) + ), + integer: option::none() } } else { OptionalAggregator { aggregator: option::none(), - integer: option::some(new_integer(limit)), + integer: option::some(new_integer(limit)) } } } @@ -136,7 +135,9 @@ module supra_framework::optional_aggregator { } /// Destroys parallelizable optional aggregator and returns its limit. - fun destroy_optional_aggregator(optional_aggregator: OptionalAggregator): u128 { + fun destroy_optional_aggregator( + optional_aggregator: OptionalAggregator + ): u128 { let OptionalAggregator { aggregator, integer } = optional_aggregator; let limit = aggregator::limit(option::borrow(&aggregator)); aggregator::destroy(option::destroy_some(aggregator)); @@ -154,7 +155,9 @@ module supra_framework::optional_aggregator { } /// Adds `value` to optional aggregator, aborting on exceeding the `limit`. - public fun add(optional_aggregator: &mut OptionalAggregator, value: u128) { + public fun add( + optional_aggregator: &mut OptionalAggregator, value: u128 + ) { if (option::is_some(&optional_aggregator.aggregator)) { let aggregator = option::borrow_mut(&mut optional_aggregator.aggregator); aggregator::add(aggregator, value); @@ -165,7 +168,9 @@ module supra_framework::optional_aggregator { } /// Subtracts `value` from optional aggregator, aborting on going below zero. - public fun sub(optional_aggregator: &mut OptionalAggregator, value: u128) { + public fun sub( + optional_aggregator: &mut OptionalAggregator, value: u128 + ) { if (option::is_some(&optional_aggregator.aggregator)) { let aggregator = option::borrow_mut(&mut optional_aggregator.aggregator); aggregator::sub(aggregator, value); diff --git a/aptos-move/framework/supra-framework/sources/aggregator/optional_aggregator.spec.move b/aptos-move/framework/supra-framework/sources/aggregator/optional_aggregator.spec.move index a490e236f0d44..1ad5e3f731324 100644 --- a/aptos-move/framework/supra-framework/sources/aggregator/optional_aggregator.spec.move +++ b/aptos-move/framework/supra-framework/sources/aggregator/optional_aggregator.spec.move @@ -30,11 +30,15 @@ spec supra_framework::optional_aggregator { } spec OptionalAggregator { - invariant option::is_some(aggregator) <==> option::is_none(integer); - invariant option::is_some(integer) <==> option::is_none(aggregator); - invariant option::is_some(integer) ==> option::borrow(integer).value <= option::borrow(integer).limit; - invariant option::is_some(aggregator) ==> aggregator::spec_aggregator_get_val(option::borrow(aggregator)) <= - aggregator::spec_get_limit(option::borrow(aggregator)); + invariant option::is_some(aggregator) <==> + option::is_none(integer); + invariant option::is_some(integer) <==> + option::is_none(aggregator); + invariant option::is_some(integer) ==> + option::borrow(integer).value <= option::borrow(integer).limit; + invariant option::is_some(aggregator) ==> + aggregator::spec_aggregator_get_val(option::borrow(aggregator)) + <= aggregator::spec_get_limit(option::borrow(aggregator)); } spec new_integer(limit: u128): Integer { @@ -69,48 +73,79 @@ spec supra_framework::optional_aggregator { spec sub(optional_aggregator: &mut OptionalAggregator, value: u128) { include SubAbortsIf; - ensures ((optional_aggregator_value(optional_aggregator) == optional_aggregator_value(old(optional_aggregator)) - value)); + ensures (( + optional_aggregator_value(optional_aggregator) + == optional_aggregator_value(old(optional_aggregator)) - value + )); } spec schema SubAbortsIf { optional_aggregator: OptionalAggregator; value: u128; - aborts_if is_parallelizable(optional_aggregator) && (aggregator::spec_aggregator_get_val(option::borrow(optional_aggregator.aggregator)) - < value); - aborts_if !is_parallelizable(optional_aggregator) && - (option::borrow(optional_aggregator.integer).value < value); + aborts_if is_parallelizable(optional_aggregator) + && ( + aggregator::spec_aggregator_get_val( + option::borrow(optional_aggregator.aggregator) + ) < value + ); + aborts_if !is_parallelizable(optional_aggregator) + && (option::borrow(optional_aggregator.integer).value < value); } spec read(optional_aggregator: &OptionalAggregator): u128 { - ensures !is_parallelizable(optional_aggregator) ==> result == option::borrow(optional_aggregator.integer).value; + ensures !is_parallelizable(optional_aggregator) ==> + result == option::borrow(optional_aggregator.integer).value; ensures is_parallelizable(optional_aggregator) ==> - result == aggregator::spec_read(option::borrow(optional_aggregator.aggregator)); + result + == aggregator::spec_read(option::borrow(optional_aggregator.aggregator)); } spec add(optional_aggregator: &mut OptionalAggregator, value: u128) { include AddAbortsIf; - ensures ((optional_aggregator_value(optional_aggregator) == optional_aggregator_value(old(optional_aggregator)) + value)); + ensures (( + optional_aggregator_value(optional_aggregator) + == optional_aggregator_value(old(optional_aggregator)) + value + )); } spec schema AddAbortsIf { optional_aggregator: OptionalAggregator; value: u128; - aborts_if is_parallelizable(optional_aggregator) && (aggregator::spec_aggregator_get_val(option::borrow(optional_aggregator.aggregator)) - + value > aggregator::spec_get_limit(option::borrow(optional_aggregator.aggregator))); - aborts_if is_parallelizable(optional_aggregator) && (aggregator::spec_aggregator_get_val(option::borrow(optional_aggregator.aggregator)) - + value > MAX_U128); - aborts_if !is_parallelizable(optional_aggregator) && - (option::borrow(optional_aggregator.integer).value + value > MAX_U128); - aborts_if !is_parallelizable(optional_aggregator) && - (value > (option::borrow(optional_aggregator.integer).limit - option::borrow(optional_aggregator.integer).value)); + aborts_if is_parallelizable(optional_aggregator) + && ( + aggregator::spec_aggregator_get_val( + option::borrow(optional_aggregator.aggregator) + ) + value + > aggregator::spec_get_limit( + option::borrow(optional_aggregator.aggregator) + ) + ); + aborts_if is_parallelizable(optional_aggregator) + && ( + aggregator::spec_aggregator_get_val( + option::borrow(optional_aggregator.aggregator) + ) + value > MAX_U128 + ); + aborts_if !is_parallelizable(optional_aggregator) + && (option::borrow(optional_aggregator.integer).value + value > MAX_U128); + aborts_if !is_parallelizable(optional_aggregator) + && ( + value + > ( + option::borrow(optional_aggregator.integer).limit + - option::borrow(optional_aggregator.integer).value + ) + ); } spec switch(optional_aggregator: &mut OptionalAggregator) { let vec_ref = optional_aggregator.integer.vec; aborts_if is_parallelizable(optional_aggregator) && len(vec_ref) != 0; aborts_if !is_parallelizable(optional_aggregator) && len(vec_ref) == 0; - aborts_if !is_parallelizable(optional_aggregator) && !exists(@supra_framework); - ensures optional_aggregator_value(optional_aggregator) == optional_aggregator_value(old(optional_aggregator)); + aborts_if !is_parallelizable(optional_aggregator) + && !exists(@supra_framework); + ensures optional_aggregator_value(optional_aggregator) + == optional_aggregator_value(old(optional_aggregator)); } spec sub_integer(integer: &mut Integer, value: u128) { @@ -119,7 +154,8 @@ spec supra_framework::optional_aggregator { } spec new(limit: u128, parallelizable: bool): OptionalAggregator { - aborts_if parallelizable && !exists(@supra_framework); + aborts_if parallelizable + && !exists(@supra_framework); ensures parallelizable ==> is_parallelizable(result); ensures !parallelizable ==> !is_parallelizable(result); ensures optional_aggregator_value(result) == 0; @@ -133,18 +169,21 @@ spec supra_framework::optional_aggregator { let vec_ref = optional_aggregator.integer.vec; aborts_if is_parallelizable(optional_aggregator) && len(vec_ref) != 0; aborts_if !is_parallelizable(optional_aggregator) && len(vec_ref) == 0; - aborts_if !is_parallelizable(optional_aggregator) && !exists(@supra_framework); + aborts_if !is_parallelizable(optional_aggregator) + && !exists(@supra_framework); /// [high-level-req-3] - ensures is_parallelizable(old(optional_aggregator)) ==> !is_parallelizable(optional_aggregator); - ensures !is_parallelizable(old(optional_aggregator)) ==> is_parallelizable(optional_aggregator); + ensures is_parallelizable(old(optional_aggregator)) ==> + !is_parallelizable(optional_aggregator); + ensures !is_parallelizable(old(optional_aggregator)) ==> + is_parallelizable(optional_aggregator); ensures optional_aggregator_value(optional_aggregator) == 0; } /// The aggregator exists and the integer dosex not exist when Switches from parallelizable to non-parallelizable implementation. - spec switch_to_integer_and_zero_out( - optional_aggregator: &mut OptionalAggregator - ): u128 { - let limit = aggregator::spec_get_limit(option::borrow(optional_aggregator.aggregator)); + spec switch_to_integer_and_zero_out(optional_aggregator: &mut OptionalAggregator): u128 { + let limit = aggregator::spec_get_limit( + option::borrow(optional_aggregator.aggregator) + ); aborts_if len(optional_aggregator.aggregator.vec) == 0; aborts_if len(optional_aggregator.integer.vec) != 0; ensures !is_parallelizable(optional_aggregator); @@ -154,28 +193,32 @@ spec supra_framework::optional_aggregator { /// The integer exists and the aggregator does not exist when Switches from non-parallelizable to parallelizable implementation. /// The AggregatorFactory is under the @supra_framework. - spec switch_to_aggregator_and_zero_out( - optional_aggregator: &mut OptionalAggregator - ): u128 { + spec switch_to_aggregator_and_zero_out(optional_aggregator: &mut OptionalAggregator): u128 { let limit = option::borrow(optional_aggregator.integer).limit; aborts_if len(optional_aggregator.integer.vec) == 0; aborts_if !exists(@supra_framework); aborts_if len(optional_aggregator.aggregator.vec) != 0; ensures is_parallelizable(optional_aggregator); - ensures aggregator::spec_get_limit(option::borrow(optional_aggregator.aggregator)) == limit; - ensures aggregator::spec_aggregator_get_val(option::borrow(optional_aggregator.aggregator)) == 0; + ensures aggregator::spec_get_limit(option::borrow(optional_aggregator.aggregator)) == + limit; + ensures aggregator::spec_aggregator_get_val( + option::borrow(optional_aggregator.aggregator) + ) == 0; } spec destroy(optional_aggregator: OptionalAggregator) { - aborts_if is_parallelizable(optional_aggregator) && len(optional_aggregator.integer.vec) != 0; - aborts_if !is_parallelizable(optional_aggregator) && len(optional_aggregator.integer.vec) == 0; + aborts_if is_parallelizable(optional_aggregator) + && len(optional_aggregator.integer.vec) != 0; + aborts_if !is_parallelizable(optional_aggregator) + && len(optional_aggregator.integer.vec) == 0; } /// The aggregator exists and the integer does not exist when destroy the aggregator. spec destroy_optional_aggregator(optional_aggregator: OptionalAggregator): u128 { aborts_if len(optional_aggregator.aggregator.vec) == 0; aborts_if len(optional_aggregator.integer.vec) != 0; - ensures result == aggregator::spec_get_limit(option::borrow(optional_aggregator.aggregator)); + ensures result + == aggregator::spec_get_limit(option::borrow(optional_aggregator.aggregator)); } /// The integer exists and the aggregator does not exist when destroy the integer. @@ -187,7 +230,9 @@ spec supra_framework::optional_aggregator { spec fun optional_aggregator_value(optional_aggregator: OptionalAggregator): u128 { if (is_parallelizable(optional_aggregator)) { - aggregator::spec_aggregator_get_val(option::borrow(optional_aggregator.aggregator)) + aggregator::spec_aggregator_get_val( + option::borrow(optional_aggregator.aggregator) + ) } else { option::borrow(optional_aggregator.integer).value } @@ -200,5 +245,4 @@ spec supra_framework::optional_aggregator { option::borrow(optional_aggregator.integer).limit } } - } diff --git a/aptos-move/framework/supra-framework/sources/aggregator_v2/aggregator_v2.move b/aptos-move/framework/supra-framework/sources/aggregator_v2/aggregator_v2.move index 6b8ce7fd9a89e..9c295d966e659 100644 --- a/aptos-move/framework/supra-framework/sources/aggregator_v2/aggregator_v2.move +++ b/aptos-move/framework/supra-framework/sources/aggregator_v2/aggregator_v2.move @@ -51,23 +51,25 @@ module supra_framework::aggregator_v2 { /// Currently supported types for IntElement are u64 and u128. struct Aggregator has store, drop { value: IntElement, - max_value: IntElement, + max_value: IntElement } /// Represents a constant value, that was derived from an aggregator at given instant in time. /// Unlike read() and storing the value directly, this enables parallel execution of transactions, /// while storing snapshot of aggregator state elsewhere. struct AggregatorSnapshot has store, drop { - value: IntElement, + value: IntElement } struct DerivedStringSnapshot has store, drop { value: String, - padding: vector, + padding: vector } /// Returns `max_value` exceeding which aggregator overflows. - public fun max_value(aggregator: &Aggregator): IntElement { + public fun max_value( + aggregator: &Aggregator + ): IntElement { aggregator.max_value } @@ -75,9 +77,13 @@ module supra_framework::aggregator_v2 { /// /// Currently supported types for IntElement are u64 and u128. /// EAGGREGATOR_ELEMENT_TYPE_NOT_SUPPORTED raised if called with a different type. - public native fun create_aggregator(max_value: IntElement): Aggregator; + public native fun create_aggregator( + max_value: IntElement + ): Aggregator; - public fun create_aggregator_with_value(start_value: IntElement, max_value: IntElement): Aggregator { + public fun create_aggregator_with_value( + start_value: IntElement, max_value: IntElement + ): Aggregator { let aggregator = create_aggregator(max_value); add(&mut aggregator, start_value); aggregator @@ -88,9 +94,12 @@ module supra_framework::aggregator_v2 { /// /// Currently supported types for IntElement are u64 and u128. /// EAGGREGATOR_ELEMENT_TYPE_NOT_SUPPORTED raised if called with a different type. - public native fun create_unbounded_aggregator(): Aggregator; + public native fun create_unbounded_aggregator(): + Aggregator; - public fun create_unbounded_aggregator_with_value(start_value: IntElement): Aggregator { + public fun create_unbounded_aggregator_with_value( + start_value: IntElement + ): Aggregator { let aggregator = create_unbounded_aggregator(); add(&mut aggregator, start_value); aggregator @@ -100,13 +109,17 @@ module supra_framework::aggregator_v2 { /// If addition would exceed the max_value, `false` is returned, and aggregator value is left unchanged. /// /// Parallelism info: This operation enables speculative parallelism. - public native fun try_add(aggregator: &mut Aggregator, value: IntElement): bool; + public native fun try_add( + aggregator: &mut Aggregator, value: IntElement + ): bool; /// Adds `value` to aggregator, unconditionally. /// If addition would exceed the max_value, EAGGREGATOR_OVERFLOW exception will be thrown. /// /// Parallelism info: This operation enables speculative parallelism. - public fun add(aggregator: &mut Aggregator, value: IntElement) { + public fun add( + aggregator: &mut Aggregator, value: IntElement + ) { assert!(try_add(aggregator, value), error::out_of_range(EAGGREGATOR_OVERFLOW)); } @@ -114,17 +127,23 @@ module supra_framework::aggregator_v2 { /// If subtraction would result in a negative value, `false` is returned, and aggregator value is left unchanged. /// /// Parallelism info: This operation enables speculative parallelism. - public native fun try_sub(aggregator: &mut Aggregator, value: IntElement): bool; + public native fun try_sub( + aggregator: &mut Aggregator, value: IntElement + ): bool; // Subtracts `value` to aggregator, unconditionally. // If subtraction would result in a negative value, EAGGREGATOR_UNDERFLOW exception will be thrown. /// /// Parallelism info: This operation enables speculative parallelism. - public fun sub(aggregator: &mut Aggregator, value: IntElement) { + public fun sub( + aggregator: &mut Aggregator, value: IntElement + ) { assert!(try_sub(aggregator, value), error::out_of_range(EAGGREGATOR_UNDERFLOW)); } - native fun is_at_least_impl(aggregator: &Aggregator, min_amount: IntElement): bool; + native fun is_at_least_impl( + aggregator: &Aggregator, min_amount: IntElement + ): bool; /// Returns true if aggregator value is larger than or equal to the given `min_amount`, false otherwise. /// @@ -134,8 +153,13 @@ module supra_framework::aggregator_v2 { /// - for `is_equal(agg, value)`, you can do `is_at_least(value) && !is_at_least(value + 1)` /// /// Parallelism info: This operation enables speculative parallelism. - public fun is_at_least(aggregator: &Aggregator, min_amount: IntElement): bool { - assert!(features::aggregator_v2_is_at_least_api_enabled(), EAGGREGATOR_API_V2_NOT_ENABLED); + public fun is_at_least( + aggregator: &Aggregator, min_amount: IntElement + ): bool { + assert!( + features::aggregator_v2_is_at_least_api_enabled(), + EAGGREGATOR_API_V2_NOT_ENABLED + ); is_at_least_impl(aggregator, min_amount) } @@ -165,11 +189,15 @@ module supra_framework::aggregator_v2 { /// Unlike read(), it is fast and avoids sequential dependencies. /// /// Parallelism info: This operation enables parallelism. - public native fun snapshot(aggregator: &Aggregator): AggregatorSnapshot; + public native fun snapshot( + aggregator: &Aggregator + ): AggregatorSnapshot; /// Creates a snapshot of a given value. /// Useful for when object is sometimes created via snapshot() or string_concat(), and sometimes directly. - public native fun create_snapshot(value: IntElement): AggregatorSnapshot; + public native fun create_snapshot( + value: IntElement + ): AggregatorSnapshot; /// Returns a value stored in this snapshot. /// Note: This operation is resource-intensive, and reduces parallelism. @@ -177,7 +205,9 @@ module supra_framework::aggregator_v2 { /// or has other read/write conflicts) /// /// Parallelism info: This operation *prevents* speculative parallelism. - public native fun read_snapshot(snapshot: &AggregatorSnapshot): IntElement; + public native fun read_snapshot( + snapshot: &AggregatorSnapshot + ): IntElement; /// Returns a value stored in this DerivedStringSnapshot. /// Note: This operation is resource-intensive, and reduces parallelism. @@ -197,17 +227,23 @@ module supra_framework::aggregator_v2 { /// If length of prefix and suffix together exceed 256 bytes, ECONCAT_STRING_LENGTH_TOO_LARGE is raised. /// /// Parallelism info: This operation enables parallelism. - public native fun derive_string_concat(before: String, snapshot: &AggregatorSnapshot, after: String): DerivedStringSnapshot; + public native fun derive_string_concat( + before: String, snapshot: &AggregatorSnapshot, after: String + ): DerivedStringSnapshot; // ===== DEPRECATE/NOT YET IMPLEMENTED ==== #[deprecated] /// NOT YET IMPLEMENTED, always raises EAGGREGATOR_FUNCTION_NOT_YET_SUPPORTED. - public native fun copy_snapshot(snapshot: &AggregatorSnapshot): AggregatorSnapshot; + public native fun copy_snapshot( + snapshot: &AggregatorSnapshot + ): AggregatorSnapshot; #[deprecated] /// DEPRECATED, use derive_string_concat() instead. always raises EAGGREGATOR_FUNCTION_NOT_YET_SUPPORTED. - public native fun string_concat(before: String, snapshot: &AggregatorSnapshot, after: String): AggregatorSnapshot; + public native fun string_concat( + before: String, snapshot: &AggregatorSnapshot, after: String + ): AggregatorSnapshot; // ======================================== @@ -283,7 +319,10 @@ module supra_framework::aggregator_v2 { #[test] fun test_string_concat1() { let snapshot = create_snapshot(42); - let derived = derive_string_concat(std::string::utf8(b"before"), &snapshot, std::string::utf8(b"after")); + let derived = + derive_string_concat( + std::string::utf8(b"before"), &snapshot, std::string::utf8(b"after") + ); assert!(read_derived_string(&derived) == std::string::utf8(b"before42after"), 0); } diff --git a/aptos-move/framework/supra-framework/sources/block.move b/aptos-move/framework/supra-framework/sources/block.move index 1f079012a5d96..3be9248613a19 100644 --- a/aptos-move/framework/supra-framework/sources/block.move +++ b/aptos-move/framework/supra-framework/sources/block.move @@ -30,14 +30,14 @@ module supra_framework::block { epoch_interval: u64, /// Handle where events with the time of new blocks are emitted new_block_events: EventHandle, - update_epoch_interval_events: EventHandle, + update_epoch_interval_events: EventHandle } /// Store new block events as a move resource, internally using a circular buffer. struct CommitHistory has key { max_capacity: u32, next_idx: u32, - table: TableWithLength, + table: TableWithLength } /// Should be in-sync with NewBlockEvent rust struct in new_block.rs @@ -50,13 +50,13 @@ module supra_framework::block { proposer: address, failed_proposer_indices: vector, /// On-chain time during the block at the given height - time_microseconds: u64, + time_microseconds: u64 } /// Event emitted when a proposal is created. struct UpdateEpochIntervalEvent has drop, store { old_epoch_interval: u64, - new_epoch_interval: u64, + new_epoch_interval: u64 } #[event] @@ -70,14 +70,14 @@ module supra_framework::block { proposer: address, failed_proposer_indices: vector, /// On-chain time during the block at the given height - time_microseconds: u64, + time_microseconds: u64 } #[event] /// Event emitted when a proposal is created. struct UpdateEpochInterval has drop, store { old_epoch_interval: u64, - new_epoch_interval: u64, + new_epoch_interval: u64 } /// The number of new block events does not equal the current block height. @@ -90,23 +90,33 @@ module supra_framework::block { const EZERO_MAX_CAPACITY: u64 = 3; /// This can only be called during Genesis. - public(friend) fun initialize(supra_framework: &signer, epoch_interval_microsecs: u64) { + public(friend) fun initialize( + supra_framework: &signer, epoch_interval_microsecs: u64 + ) { system_addresses::assert_supra_framework(supra_framework); - assert!(epoch_interval_microsecs > 0, error::invalid_argument(EZERO_EPOCH_INTERVAL)); + assert!( + epoch_interval_microsecs > 0, error::invalid_argument(EZERO_EPOCH_INTERVAL) + ); - move_to(supra_framework, CommitHistory { - max_capacity: 2000, - next_idx: 0, - table: table_with_length::new(), - }); + move_to( + supra_framework, + CommitHistory { + max_capacity: 2000, + next_idx: 0, + table: table_with_length::new() + } + ); move_to( supra_framework, BlockResource { height: 0, epoch_interval: epoch_interval_microsecs, - new_block_events: account::new_event_handle(supra_framework), - update_epoch_interval_events: account::new_event_handle(supra_framework), + new_block_events: account::new_event_handle( + supra_framework + ), + update_epoch_interval_events: account::new_event_handle< + UpdateEpochIntervalEvent>(supra_framework) } ); } @@ -114,18 +124,16 @@ module supra_framework::block { /// Initialize the commit history resource if it's not in genesis. public fun initialize_commit_history(fx: &signer, max_capacity: u32) { assert!(max_capacity > 0, error::invalid_argument(EZERO_MAX_CAPACITY)); - move_to(fx, CommitHistory { - max_capacity, - next_idx: 0, - table: table_with_length::new(), - }); + move_to( + fx, + CommitHistory { max_capacity, next_idx: 0, table: table_with_length::new() } + ); } /// Update the epoch interval. /// Can only be called as part of the Supra governance proposal process established by the AptosGovernance module. public fun update_epoch_interval_microsecs( - supra_framework: &signer, - new_epoch_interval: u64, + supra_framework: &signer, new_epoch_interval: u64 ) acquires BlockResource { system_addresses::assert_supra_framework(supra_framework); assert!(new_epoch_interval > 0, error::invalid_argument(EZERO_EPOCH_INTERVAL)); @@ -135,13 +143,11 @@ module supra_framework::block { block_resource.epoch_interval = new_epoch_interval; if (std::features::module_event_migration_enabled()) { - event::emit( - UpdateEpochInterval { old_epoch_interval, new_epoch_interval }, - ); + event::emit(UpdateEpochInterval { old_epoch_interval, new_epoch_interval }); }; event::emit_event( &mut block_resource.update_epoch_interval_events, - UpdateEpochIntervalEvent { old_epoch_interval, new_epoch_interval }, + UpdateEpochIntervalEvent { old_epoch_interval, new_epoch_interval } ); } @@ -151,7 +157,6 @@ module supra_framework::block { borrow_global(@supra_framework).epoch_interval / 1000000 } - fun block_prologue_common( vm: &signer, hash: address, @@ -168,7 +173,7 @@ module supra_framework::block { // Blocks can only be produced by a valid proposer or by the VM itself for Nil blocks (no user txs). assert!( proposer == @vm_reserved || stake::is_current_epoch_validator(proposer), - error::permission_denied(EINVALID_PROPOSER), + error::permission_denied(EINVALID_PROPOSER) ); let proposer_index = option::none(); @@ -188,7 +193,7 @@ module supra_framework::block { previous_block_votes_bitvec, proposer, failed_proposer_indices, - time_microseconds: timestamp, + time_microseconds: timestamp }; let new_block_event_v2 = NewBlock { hash, @@ -198,9 +203,14 @@ module supra_framework::block { previous_block_votes_bitvec, proposer, failed_proposer_indices, - time_microseconds: timestamp, + time_microseconds: timestamp }; - emit_new_block_event(vm, &mut block_metadata_ref.new_block_events, new_block_event, new_block_event_v2); + emit_new_block_event( + vm, + &mut block_metadata_ref.new_block_events, + new_block_event, + new_block_event_v2 + ); if (features::collect_and_distribute_gas_fees()) { // Assign the fees collected from the previous block to the previous block proposer. @@ -231,7 +241,17 @@ module supra_framework::block { previous_block_votes_bitvec: vector, timestamp: u64 ) acquires BlockResource, CommitHistory { - let epoch_interval = block_prologue_common(&vm, hash, epoch, round, proposer, failed_proposer_indices, previous_block_votes_bitvec, timestamp); + let epoch_interval = + block_prologue_common( + &vm, + hash, + epoch, + round, + proposer, + failed_proposer_indices, + previous_block_votes_bitvec, + timestamp + ); randomness::on_new_block(&vm, epoch, round, option::none()); if (timestamp - reconfiguration::last_reconfiguration_time() >= epoch_interval) { reconfiguration::reconfigure(); @@ -248,18 +268,19 @@ module supra_framework::block { failed_proposer_indices: vector, previous_block_votes_bitvec: vector, timestamp: u64, - randomness_seed: Option>, + randomness_seed: Option> ) acquires BlockResource, CommitHistory { - let epoch_interval = block_prologue_common( - &vm, - hash, - epoch, - round, - proposer, - failed_proposer_indices, - previous_block_votes_bitvec, - timestamp - ); + let epoch_interval = + block_prologue_common( + &vm, + hash, + epoch, + round, + proposer, + failed_proposer_indices, + previous_block_votes_bitvec, + timestamp + ); randomness::on_new_block(&vm, epoch, round, randomness_seed); if (timestamp - reconfiguration::last_reconfiguration_time() >= epoch_interval) { @@ -286,16 +307,20 @@ module supra_framework::block { if (table_with_length::contains(&commit_history_ref.table, idx)) { table_with_length::remove(&mut commit_history_ref.table, idx); }; - table_with_length::add(&mut commit_history_ref.table, idx, copy new_block_event); + table_with_length::add( + &mut commit_history_ref.table, idx, copy new_block_event + ); spec { assume idx + 1 <= MAX_U32; }; commit_history_ref.next_idx = (idx + 1) % commit_history_ref.max_capacity; }; - timestamp::update_global_time(vm, new_block_event.proposer, new_block_event.time_microseconds); + timestamp::update_global_time( + vm, new_block_event.proposer, new_block_event.time_microseconds + ); assert!( event::counter(event_handle) == new_block_event.height, - error::invalid_argument(ENUM_NEW_BLOCK_EVENTS_DOES_NOT_MATCH_BLOCK_HEIGHT), + error::invalid_argument(ENUM_NEW_BLOCK_EVENTS_DOES_NOT_MATCH_BLOCK_HEIGHT) ); if (std::features::module_event_migration_enabled()) { event::emit(new_block_event_v2); @@ -319,7 +344,7 @@ module supra_framework::block { previous_block_votes_bitvec: vector::empty(), proposer: @vm_reserved, failed_proposer_indices: vector::empty(), - time_microseconds: timestamp::now_microseconds(), + time_microseconds: timestamp::now_microseconds() }, NewBlock { hash: genesis_id, @@ -329,14 +354,16 @@ module supra_framework::block { previous_block_votes_bitvec: vector::empty(), proposer: @vm_reserved, failed_proposer_indices: vector::empty(), - time_microseconds: timestamp::now_microseconds(), + time_microseconds: timestamp::now_microseconds() } ); } /// Emit a `NewBlockEvent` event. This function will be invoked by write set script directly to generate the /// new block event for WriteSetPayload. - public fun emit_writeset_block_event(vm_signer: &signer, fake_block_hash: address) acquires BlockResource, CommitHistory { + public fun emit_writeset_block_event( + vm_signer: &signer, fake_block_hash: address + ) acquires BlockResource, CommitHistory { system_addresses::assert_vm(vm_signer); let block_metadata_ref = borrow_global_mut(@supra_framework); block_metadata_ref.height = event::counter(&block_metadata_ref.new_block_events); @@ -352,7 +379,7 @@ module supra_framework::block { previous_block_votes_bitvec: vector::empty(), proposer: @vm_reserved, failed_proposer_indices: vector::empty(), - time_microseconds: timestamp::now_microseconds(), + time_microseconds: timestamp::now_microseconds() }, NewBlock { hash: fake_block_hash, @@ -362,13 +389,15 @@ module supra_framework::block { previous_block_votes_bitvec: vector::empty(), proposer: @vm_reserved, failed_proposer_indices: vector::empty(), - time_microseconds: timestamp::now_microseconds(), + time_microseconds: timestamp::now_microseconds() } ); } #[test_only] - public fun initialize_for_test(account: &signer, epoch_interval_microsecs: u64) { + public fun initialize_for_test( + account: &signer, epoch_interval_microsecs: u64 + ) { initialize(account, epoch_interval_microsecs); } @@ -384,8 +413,7 @@ module supra_framework::block { #[test(supra_framework = @supra_framework, account = @0x123)] #[expected_failure(abort_code = 0x50003, location = supra_framework::system_addresses)] public entry fun test_update_epoch_interval_unauthorized_should_fail( - supra_framework: signer, - account: signer, + supra_framework: signer, account: signer ) acquires BlockResource { account::create_account_for_test(@supra_framework); initialize(&supra_framework, 1); diff --git a/aptos-move/framework/supra-framework/sources/block.spec.move b/aptos-move/framework/supra-framework/sources/block.spec.move index e7dc0715a33a2..6b706f0995002 100644 --- a/aptos-move/framework/supra-framework/sources/block.spec.move +++ b/aptos-move/framework/supra-framework/sources/block.spec.move @@ -43,9 +43,11 @@ spec supra_framework::block { spec module { use supra_framework::chain_status; // After genesis, `BlockResource` exist. - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); // After genesis, `CommitHistory` exist. - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); } spec BlockResource { @@ -64,7 +66,6 @@ spec supra_framework::block { } spec block_prologue { - pragma verify_duration_estimate = 1000; // TODO: set because of timeout (property proved) requires timestamp >= reconfiguration::last_reconfiguration_time(); include BlockRequirement; @@ -85,7 +86,8 @@ spec supra_framework::block { requires chain_status::is_operating(); requires system_addresses::is_vm(vm); - requires event::counter(global(@supra_framework).new_block_events) == 0; + requires event::counter(global(@supra_framework).new_block_events) == + 0; requires (timestamp::spec_now_microseconds() == 0); aborts_if false; @@ -98,8 +100,10 @@ spec supra_framework::block { requires chain_status::is_operating(); requires system_addresses::is_vm(vm); - requires (proposer == @vm_reserved) ==> (timestamp::spec_now_microseconds() == timestamp); - requires (proposer != @vm_reserved) ==> (timestamp::spec_now_microseconds() < timestamp); + requires (proposer == @vm_reserved) ==> + (timestamp::spec_now_microseconds() == timestamp); + requires (proposer != @vm_reserved) ==> + (timestamp::spec_now_microseconds() < timestamp); /// [high-level-req-5] requires event::counter(event_handle) == new_block_event.height; @@ -142,9 +146,12 @@ spec supra_framework::block { requires chain_status::is_operating(); requires system_addresses::is_vm(vm); /// [high-level-req-4] - requires proposer == @vm_reserved || stake::spec_is_current_epoch_validator(proposer); - requires (proposer == @vm_reserved) ==> (timestamp::spec_now_microseconds() == timestamp); - requires (proposer != @vm_reserved) ==> (timestamp::spec_now_microseconds() < timestamp); + requires proposer == @vm_reserved + || stake::spec_is_current_epoch_validator(proposer); + requires (proposer == @vm_reserved) ==> + (timestamp::spec_now_microseconds() == timestamp); + requires (proposer != @vm_reserved) ==> + (timestamp::spec_now_microseconds() < timestamp); requires exists(@supra_framework); requires exists>(@supra_framework); include transaction_fee::RequiresCollectedFeesPerValueLeqBlockAptosSupply; @@ -180,10 +187,7 @@ spec supra_framework::block { /// The caller is @supra_framework. /// The new_epoch_interval must be greater than 0. /// The BlockResource existed under the @supra_framework. - spec update_epoch_interval_microsecs( - supra_framework: &signer, - new_epoch_interval: u64, - ) { + spec update_epoch_interval_microsecs(supra_framework: &signer, new_epoch_interval: u64) { /// [high-level-req-3.1] include UpdateEpochIntervalMicrosecs; } diff --git a/aptos-move/framework/supra-framework/sources/code.move b/aptos-move/framework/supra-framework/sources/code.move index 672132ded7eb6..ac7fb9a30b671 100644 --- a/aptos-move/framework/supra-framework/sources/code.move +++ b/aptos-move/framework/supra-framework/sources/code.move @@ -20,7 +20,7 @@ module supra_framework::code { /// The package registry at the given address. struct PackageRegistry has key, store, drop { /// Packages installed at this address. - packages: vector, + packages: vector } /// Metadata for a package. All byte blobs are represented as base64-of-gzipped-bytes @@ -60,7 +60,7 @@ module supra_framework::code { /// Source map, in compressed BCS. Empty if not provided. source_map: vector, /// For future extensions. - extension: Option, + extension: Option } /// Describes an upgrade policy @@ -72,7 +72,7 @@ module supra_framework::code { /// Event emitted when code is published to an address. struct PublishPackage has drop, store { code_address: address, - is_upgrade: bool, + is_upgrade: bool } /// Package contains duplicate module names with existing modules publised in other packages on this address @@ -126,29 +126,36 @@ module supra_framework::code { /// Whether the upgrade policy can be changed. In general, the policy can be only /// strengthened but not weakened. - public fun can_change_upgrade_policy_to(from: UpgradePolicy, to: UpgradePolicy): bool { + public fun can_change_upgrade_policy_to( + from: UpgradePolicy, to: UpgradePolicy + ): bool { from.policy <= to.policy } /// Initialize package metadata for Genesis. - fun initialize(supra_framework: &signer, package_owner: &signer, metadata: PackageMetadata) - acquires PackageRegistry { + fun initialize( + supra_framework: &signer, package_owner: &signer, metadata: PackageMetadata + ) acquires PackageRegistry { system_addresses::assert_supra_framework(supra_framework); let addr = signer::address_of(package_owner); if (!exists(addr)) { move_to(package_owner, PackageRegistry { packages: vector[metadata] }) } else { - vector::push_back(&mut borrow_global_mut(addr).packages, metadata) + vector::push_back( + &mut borrow_global_mut(addr).packages, metadata + ) } } /// Publishes a package at the given signer's address. The caller must provide package metadata describing the /// package. - public fun publish_package(owner: &signer, pack: PackageMetadata, code: vector>) acquires PackageRegistry { + public fun publish_package( + owner: &signer, pack: PackageMetadata, code: vector> + ) acquires PackageRegistry { // Disallow incompatible upgrade mode. Governance can decide later if this should be reconsidered. assert!( pack.upgrade_policy.policy > upgrade_policy_arbitrary().policy, - error::invalid_argument(EINCOMPATIBLE_POLICY_DISABLED), + error::invalid_argument(EINCOMPATIBLE_POLICY_DISABLED) ); let addr = signer::address_of(owner); @@ -167,17 +174,19 @@ module supra_framework::code { let len = vector::length(package_immutable); let index = len; let upgrade_number = 0; - vector::enumerate_ref(package_immutable - , |i, old| { - let old: &PackageMetadata = old; - if (old.name == pack.name) { - upgrade_number = old.upgrade_number + 1; - check_upgradability(old, &pack, &module_names); - index = i; - } else { - check_coexistence(old, &module_names) - }; - }); + vector::enumerate_ref( + package_immutable, + |i, old| { + let old: &PackageMetadata = old; + if (old.name == pack.name) { + upgrade_number = old.upgrade_number + 1; + check_upgradability(old, &pack, &module_names); + index = i; + } else { + check_coexistence(old, &module_names) + }; + } + ); // Assign the upgrade counter. pack.upgrade_number = upgrade_number; @@ -191,48 +200,62 @@ module supra_framework::code { vector::push_back(packages, pack) }; - event::emit(PublishPackage { - code_address: addr, - is_upgrade: upgrade_number > 0 - }); + event::emit( + PublishPackage { code_address: addr, is_upgrade: upgrade_number > 0 } + ); // Request publish if (features::code_dependency_check_enabled()) - request_publish_with_allowed_deps(addr, module_names, allowed_deps, code, policy.policy) - else + request_publish_with_allowed_deps( + addr, module_names, allowed_deps, code, policy.policy + ) else // The new `request_publish_with_allowed_deps` has not yet rolled out, so call downwards // compatible code. - request_publish(addr, module_names, code, policy.policy) + request_publish(addr, module_names, code, policy.policy) } - public fun freeze_code_object(publisher: &signer, code_object: Object) acquires PackageRegistry { + public fun freeze_code_object( + publisher: &signer, code_object: Object + ) acquires PackageRegistry { let code_object_addr = object::object_address(&code_object); - assert!(exists(code_object_addr), error::not_found(ECODE_OBJECT_DOES_NOT_EXIST)); + assert!( + exists(code_object_addr), + error::not_found(ECODE_OBJECT_DOES_NOT_EXIST) + ); assert!( object::is_owner(code_object, signer::address_of(publisher)), error::permission_denied(ENOT_PACKAGE_OWNER) ); let registry = borrow_global_mut(code_object_addr); - vector::for_each_mut(&mut registry.packages, |pack| { - let package: &mut PackageMetadata = pack; - package.upgrade_policy = upgrade_policy_immutable(); - }); + vector::for_each_mut( + &mut registry.packages, + |pack| { + let package: &mut PackageMetadata = pack; + package.upgrade_policy = upgrade_policy_immutable(); + } + ); // We unfortunately have to make a copy of each package to avoid borrow checker issues as check_dependencies // needs to borrow PackageRegistry from the dependency packages. // This would increase the amount of gas used, but this is a rare operation and it's rare to have many packages // in a single code object. - vector::for_each(registry.packages, |pack| { - check_dependencies(code_object_addr, &pack); - }); + vector::for_each( + registry.packages, + |pack| { + check_dependencies(code_object_addr, &pack); + } + ); } /// Same as `publish_package` but as an entry function which can be called as a transaction. Because /// of current restrictions for txn parameters, the metadata needs to be passed in serialized form. - public entry fun publish_package_txn(owner: &signer, metadata_serialized: vector, code: vector>) - acquires PackageRegistry { - publish_package(owner, util::from_bytes(metadata_serialized), code) + public entry fun publish_package_txn( + owner: &signer, metadata_serialized: vector, code: vector> + ) acquires PackageRegistry { + publish_package( + owner, util::from_bytes(metadata_serialized), code + ) } // Helpers @@ -240,83 +263,118 @@ module supra_framework::code { /// Checks whether the given package is upgradable, and returns true if a compatibility check is needed. fun check_upgradability( - old_pack: &PackageMetadata, new_pack: &PackageMetadata, new_modules: &vector) { - assert!(old_pack.upgrade_policy.policy < upgrade_policy_immutable().policy, - error::invalid_argument(EUPGRADE_IMMUTABLE)); - assert!(can_change_upgrade_policy_to(old_pack.upgrade_policy, new_pack.upgrade_policy), - error::invalid_argument(EUPGRADE_WEAKER_POLICY)); + old_pack: &PackageMetadata, + new_pack: &PackageMetadata, + new_modules: &vector + ) { + assert!( + old_pack.upgrade_policy.policy < upgrade_policy_immutable().policy, + error::invalid_argument(EUPGRADE_IMMUTABLE) + ); + assert!( + can_change_upgrade_policy_to(old_pack.upgrade_policy, new_pack.upgrade_policy), + error::invalid_argument(EUPGRADE_WEAKER_POLICY) + ); let old_modules = get_module_names(old_pack); - vector::for_each_ref(&old_modules, |old_module| { - assert!( - vector::contains(new_modules, old_module), - EMODULE_MISSING - ); - }); + vector::for_each_ref( + &old_modules, + |old_module| { + assert!( + vector::contains(new_modules, old_module), + EMODULE_MISSING + ); + } + ); } /// Checks whether a new package with given names can co-exist with old package. - fun check_coexistence(old_pack: &PackageMetadata, new_modules: &vector) { + fun check_coexistence( + old_pack: &PackageMetadata, new_modules: &vector + ) { // The modules introduced by each package must not overlap with `names`. - vector::for_each_ref(&old_pack.modules, |old_mod| { - let old_mod: &ModuleMetadata = old_mod; - let j = 0; - while (j < vector::length(new_modules)) { - let name = vector::borrow(new_modules, j); - assert!(&old_mod.name != name, error::already_exists(EMODULE_NAME_CLASH)); - j = j + 1; - }; - }); + vector::for_each_ref( + &old_pack.modules, + |old_mod| { + let old_mod: &ModuleMetadata = old_mod; + let j = 0; + while (j < vector::length(new_modules)) { + let name = vector::borrow(new_modules, j); + assert!( + &old_mod.name != name, error::already_exists(EMODULE_NAME_CLASH) + ); + j = j + 1; + }; + } + ); } /// Check that the upgrade policies of all packages are equal or higher quality than this package. Also /// compute the list of module dependencies which are allowed by the package metadata. The later /// is passed on to the native layer to verify that bytecode dependencies are actually what is pretended here. - fun check_dependencies(publish_address: address, pack: &PackageMetadata): vector - acquires PackageRegistry { + fun check_dependencies( + publish_address: address, pack: &PackageMetadata + ): vector acquires PackageRegistry { let allowed_module_deps = vector::empty(); let deps = &pack.deps; - vector::for_each_ref(deps, |dep| { - let dep: &PackageDep = dep; - assert!(exists(dep.account), error::not_found(EPACKAGE_DEP_MISSING)); - if (is_policy_exempted_address(dep.account)) { - // Allow all modules from this address, by using "" as a wildcard in the AllowedDep - let account: address = dep.account; - let module_name = string::utf8(b""); - vector::push_back(&mut allowed_module_deps, AllowedDep { account, module_name }); - } else { - let registry = borrow_global(dep.account); - let found = vector::any(®istry.packages, |dep_pack| { - let dep_pack: &PackageMetadata = dep_pack; - if (dep_pack.name == dep.package_name) { - // Check policy - assert!( - dep_pack.upgrade_policy.policy >= pack.upgrade_policy.policy, - error::invalid_argument(EDEP_WEAKER_POLICY) - ); - if (dep_pack.upgrade_policy == upgrade_policy_arbitrary()) { - assert!( - dep.account == publish_address, - error::invalid_argument(EDEP_ARBITRARY_NOT_SAME_ADDRESS) - ) - }; - // Add allowed deps - let account = dep.account; - let k = 0; - let r = vector::length(&dep_pack.modules); - while (k < r) { - let module_name = vector::borrow(&dep_pack.modules, k).name; - vector::push_back(&mut allowed_module_deps, AllowedDep { account, module_name }); - k = k + 1; - }; - true - } else { - false - } - }); - assert!(found, error::not_found(EPACKAGE_DEP_MISSING)); - }; - }); + vector::for_each_ref( + deps, + |dep| { + let dep: &PackageDep = dep; + assert!( + exists(dep.account), + error::not_found(EPACKAGE_DEP_MISSING) + ); + if (is_policy_exempted_address(dep.account)) { + // Allow all modules from this address, by using "" as a wildcard in the AllowedDep + let account: address = dep.account; + let module_name = string::utf8(b""); + vector::push_back( + &mut allowed_module_deps, AllowedDep { account, module_name } + ); + } else { + let registry = borrow_global(dep.account); + let found = vector::any( + ®istry.packages, + |dep_pack| { + let dep_pack: &PackageMetadata = dep_pack; + if (dep_pack.name == dep.package_name) { + // Check policy + assert!( + dep_pack.upgrade_policy.policy + >= pack.upgrade_policy.policy, + error::invalid_argument(EDEP_WEAKER_POLICY) + ); + if (dep_pack.upgrade_policy + == upgrade_policy_arbitrary()) { + assert!( + dep.account == publish_address, + error::invalid_argument( + EDEP_ARBITRARY_NOT_SAME_ADDRESS + ) + ) + }; + // Add allowed deps + let account = dep.account; + let k = 0; + let r = vector::length(&dep_pack.modules); + while (k < r) { + let module_name = vector::borrow(&dep_pack.modules, k) + .name; + vector::push_back( + &mut allowed_module_deps, + AllowedDep { account, module_name } + ); + k = k + 1; + }; + true + } else { false } + } + ); + assert!(found, error::not_found(EPACKAGE_DEP_MISSING)); + }; + } + ); allowed_module_deps } @@ -324,17 +382,28 @@ module supra_framework::code { /// this exemption, it would not be possible to define an immutable package based on the core system, which /// requires to be upgradable for maintenance and evolution, and is configured to be `compatible`. fun is_policy_exempted_address(addr: address): bool { - addr == @1 || addr == @2 || addr == @3 || addr == @4 || addr == @5 || - addr == @6 || addr == @7 || addr == @8 || addr == @9 || addr == @10 + addr == @1 + || addr == @2 + || addr == @3 + || addr == @4 + || addr == @5 + || addr == @6 + || addr == @7 + || addr == @8 + || addr == @9 + || addr == @10 } /// Get the names of the modules in a package. fun get_module_names(pack: &PackageMetadata): vector { let module_names = vector::empty(); - vector::for_each_ref(&pack.modules, |pack_module| { - let pack_module: &ModuleMetadata = pack_module; - vector::push_back(&mut module_names, pack_module.name); - }); + vector::for_each_ref( + &pack.modules, + |pack_module| { + let pack_module: &ModuleMetadata = pack_module; + vector::push_back(&mut module_names, pack_module.name); + } + ); module_names } diff --git a/aptos-move/framework/supra-framework/sources/code.spec.move b/aptos-move/framework/supra-framework/sources/code.spec.move index f5d750e37341d..e790af8d3d28b 100644 --- a/aptos-move/framework/supra-framework/sources/code.spec.move +++ b/aptos-move/framework/supra-framework/sources/code.spec.move @@ -93,11 +93,15 @@ spec supra_framework::code { pragma verify = false; } - spec check_upgradability(old_pack: &PackageMetadata, new_pack: &PackageMetadata, new_modules: &vector) { + spec check_upgradability( + old_pack: &PackageMetadata, new_pack: &PackageMetadata, new_modules: &vector + ) { // TODO: Can't verify 'vector::enumerate' loop. pragma aborts_if_is_partial; aborts_if old_pack.upgrade_policy.policy >= upgrade_policy_immutable().policy; - aborts_if !can_change_upgrade_policy_to(old_pack.upgrade_policy, new_pack.upgrade_policy); + aborts_if !can_change_upgrade_policy_to( + old_pack.upgrade_policy, new_pack.upgrade_policy + ); } spec check_dependencies(publish_address: address, pack: &PackageMetadata): vector { @@ -114,7 +118,8 @@ spec supra_framework::code { pragma opaque; aborts_if [abstract] false; ensures [abstract] len(result) == len(pack.modules); - ensures [abstract] forall i in 0..len(result): result[i] == pack.modules[i].name; + ensures [abstract] forall i in 0..len(result): result[i] + == pack.modules[i].name; } spec freeze_code_object(publisher: &signer, code_object: Object) { diff --git a/aptos-move/framework/supra-framework/sources/coin.move b/aptos-move/framework/supra-framework/sources/coin.move index d96b6880474a4..ea9b73c8a3990 100644 --- a/aptos-move/framework/supra-framework/sources/coin.move +++ b/aptos-move/framework/supra-framework/sources/coin.move @@ -15,7 +15,14 @@ module supra_framework::coin { use supra_framework::optional_aggregator::{Self, OptionalAggregator}; use supra_framework::system_addresses; - use supra_framework::fungible_asset::{Self, FungibleAsset, Metadata, MintRef, TransferRef, BurnRef}; + use supra_framework::fungible_asset::{ + Self, + FungibleAsset, + Metadata, + MintRef, + TransferRef, + BurnRef + }; use supra_framework::object::{Self, Object, object_address}; use supra_framework::primary_fungible_store; use aptos_std::type_info::{Self, TypeInfo, type_name}; @@ -119,7 +126,7 @@ module supra_framework::coin { /// Main structure representing a coin/token in an account's custody. struct Coin has store { /// Amount of coin this address has. - value: u64, + value: u64 } /// Represents a coin with aggregator as its value. This allows to update @@ -127,7 +134,7 @@ module supra_framework::coin { /// used for gas fees distribution by Supra Framework (0x1). struct AggregatableCoin has store { /// Amount of aggregatable coin this address has. - value: Aggregator, + value: Aggregator } /// Maximum possible aggregatable coin value. @@ -139,7 +146,7 @@ module supra_framework::coin { coin: Coin, frozen: bool, deposit_events: EventHandle, - withdraw_events: EventHandle, + withdraw_events: EventHandle } /// Maximum possible coin supply. @@ -148,7 +155,7 @@ module supra_framework::coin { /// Configuration that controls the behavior of total coin supply. If the field /// is set, coin creators are allowed to upgrade to parallelizable implementations. struct SupplyConfig has key { - allow_upgrades: bool, + allow_upgrades: bool } /// Information about a specific coin type. Stored on the creator of the coin's account. @@ -162,16 +169,15 @@ module supra_framework::coin { /// be displayed to a user as `5.05` (`505 / 10 ** 2`). decimals: u8, /// Amount of this coin type in existence. - supply: Option, + supply: Option } - #[event] /// Module event emitted when some amount of a coin is deposited into an account. struct CoinDeposit has drop, store { coin_type: String, account: address, - amount: u64, + amount: u64 } #[event] @@ -179,7 +185,7 @@ module supra_framework::coin { struct CoinWithdraw has drop, store { coin_type: String, account: address, - amount: u64, + amount: u64 } // DEPRECATED, NEVER USED @@ -187,7 +193,7 @@ module supra_framework::coin { #[event] struct Deposit has drop, store { account: address, - amount: u64, + amount: u64 } // DEPRECATED, NEVER USED @@ -195,33 +201,32 @@ module supra_framework::coin { #[event] struct Withdraw has drop, store { account: address, - amount: u64, + amount: u64 } /// Event emitted when some amount of a coin is deposited into an account. struct DepositEvent has drop, store { - amount: u64, + amount: u64 } /// Event emitted when some amount of a coin is withdrawn from an account. struct WithdrawEvent has drop, store { - amount: u64, + amount: u64 } - #[event] /// Module event emitted when the event handles related to coin store is deleted. struct CoinEventHandleDeletion has drop, store { event_handle_creation_address: address, deleted_deposit_event_handle_creation_number: u64, - deleted_withdraw_event_handle_creation_number: u64, + deleted_withdraw_event_handle_creation_number: u64 } #[event] /// Module event emitted when a new pair of coin and fungible asset is created. struct PairCreation has drop, store { coin_type: TypeInfo, - fungible_asset_metadata_address: address, + fungible_asset_metadata_address: address } #[resource_group_member(group = supra_framework::object::ObjectGroup)] @@ -239,13 +244,13 @@ module supra_framework::coin { /// The mapping between coin and fungible asset. struct CoinConversionMap has key { - coin_to_fungible_asset_map: Table>, + coin_to_fungible_asset_map: Table> } #[resource_group_member(group = supra_framework::object::ObjectGroup)] /// The paired coin type info stored in fungible asset metadata object. struct PairedCoinType has key { - type: TypeInfo, + type: TypeInfo } #[resource_group_member(group = supra_framework::object::ObjectGroup)] @@ -253,30 +258,31 @@ module supra_framework::coin { struct PairedFungibleAssetRefs has key { mint_ref_opt: Option, transfer_ref_opt: Option, - burn_ref_opt: Option, + burn_ref_opt: Option } /// The hot potato receipt for flash borrowing MintRef. struct MintRefReceipt { - metadata: Object, + metadata: Object } /// The hot potato receipt for flash borrowing TransferRef. struct TransferRefReceipt { - metadata: Object, + metadata: Object } /// The hot potato receipt for flash borrowing BurnRef. struct BurnRefReceipt { - metadata: Object, + metadata: Object } #[view] /// Get the paired fungible asset metadata object of a coin type. If not exist, return option::none(). public fun paired_metadata(): Option> acquires CoinConversionMap { - if (exists(@supra_framework) && features::coin_to_fungible_asset_migration_feature_enabled( - )) { - let map = &borrow_global(@supra_framework).coin_to_fungible_asset_map; + if (exists(@supra_framework) + && features::coin_to_fungible_asset_migration_feature_enabled()) { + let map = + &borrow_global(@supra_framework).coin_to_fungible_asset_map; let type = type_info::type_of(); if (table::contains(map, type)) { return option::some(*table::borrow(map, type)) @@ -288,9 +294,10 @@ module supra_framework::coin { public entry fun create_coin_conversion_map(supra_framework: &signer) { system_addresses::assert_supra_framework(supra_framework); if (!exists(@supra_framework)) { - move_to(supra_framework, CoinConversionMap { - coin_to_fungible_asset_map: table::new(), - }) + move_to( + supra_framework, + CoinConversionMap { coin_to_fungible_asset_map: table::new() } + ) }; } @@ -306,20 +313,30 @@ module supra_framework::coin { type_info::type_name() == string::utf8(b"0x1::supra_coin::SupraCoin") } - inline fun create_and_return_paired_metadata_if_not_exist(allow_apt_creation: bool): Object { + inline fun create_and_return_paired_metadata_if_not_exist( + allow_apt_creation: bool + ): Object { assert!( features::coin_to_fungible_asset_migration_feature_enabled(), error::invalid_state(EMIGRATION_FRAMEWORK_NOT_ENABLED) ); - assert!(exists(@supra_framework), error::not_found(ECOIN_CONVERSION_MAP_NOT_FOUND)); + assert!( + exists(@supra_framework), + error::not_found(ECOIN_CONVERSION_MAP_NOT_FOUND) + ); let map = borrow_global_mut(@supra_framework); let type = type_info::type_of(); if (!table::contains(&map.coin_to_fungible_asset_map, type)) { let is_sup = is_sup(); - assert!(!is_sup || allow_apt_creation, error::invalid_state(EAPT_PAIRING_IS_NOT_ENABLED)); + assert!( + !is_sup || allow_apt_creation, + error::invalid_state(EAPT_PAIRING_IS_NOT_ENABLED) + ); let metadata_object_cref = if (is_sup) { - object::create_sticky_object_at_address(@supra_framework, @aptos_fungible_asset) + object::create_sticky_object_at_address( + @supra_framework, @aptos_fungible_asset + ) } else { object::create_named_object( &create_signer::create_signer(@aptos_fungible_asset), @@ -333,7 +350,7 @@ module supra_framework::coin { symbol(), decimals(), string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); let metadata_object_signer = &object::generate_signer(&metadata_object_cref); @@ -342,20 +359,24 @@ module supra_framework::coin { let metadata_obj = object::object_from_constructor_ref(&metadata_object_cref); table::add(&mut map.coin_to_fungible_asset_map, type, metadata_obj); - event::emit(PairCreation { - coin_type: type, - fungible_asset_metadata_address: object_address(&metadata_obj) - }); + event::emit( + PairCreation { + coin_type: type, + fungible_asset_metadata_address: object_address(&metadata_obj) + } + ); // Generates all three refs let mint_ref = fungible_asset::generate_mint_ref(&metadata_object_cref); - let transfer_ref = fungible_asset::generate_transfer_ref(&metadata_object_cref); + let transfer_ref = + fungible_asset::generate_transfer_ref(&metadata_object_cref); let burn_ref = fungible_asset::generate_burn_ref(&metadata_object_cref); - move_to(metadata_object_signer, + move_to( + metadata_object_signer, PairedFungibleAssetRefs { mint_ref_opt: option::some(mint_ref), transfer_ref_opt: option::some(transfer_ref), - burn_ref_opt: option::some(burn_ref), + burn_ref_opt: option::some(burn_ref) } ); }; @@ -414,13 +435,17 @@ module supra_framework::coin { fun fungible_asset_to_coin( fungible_asset: FungibleAsset ): Coin acquires CoinInfo, PairedCoinType { - let metadata_addr = object::object_address(&fungible_asset::metadata_from_asset(&fungible_asset)); + let metadata_addr = + object::object_address(&fungible_asset::metadata_from_asset(&fungible_asset)); assert!( object::object_exists(metadata_addr), error::not_found(EPAIRED_COIN) ); let coin_type_info = borrow_global(metadata_addr).type; - assert!(coin_type_info == type_info::type_of(), error::invalid_argument(ECOIN_TYPE_MISMATCH)); + assert!( + coin_type_info == type_info::type_of(), + error::invalid_argument(ECOIN_TYPE_MISMATCH) + ); let amount = fungible_asset::burn_internal(fungible_asset); mint_internal(amount) } @@ -436,8 +461,13 @@ module supra_framework::coin { public fun paired_mint_ref_exists(): bool acquires CoinConversionMap, PairedFungibleAssetRefs { let metadata = assert_paired_metadata_exists(); let metadata_addr = object_address(&metadata); - assert!(exists(metadata_addr), error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND)); - option::is_some(&borrow_global(metadata_addr).mint_ref_opt) + assert!( + exists(metadata_addr), + error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND) + ); + option::is_some( + &borrow_global(metadata_addr).mint_ref_opt + ) } /// Get the `MintRef` of paired fungible asset of a coin type from `MintCapability`. @@ -446,21 +476,28 @@ module supra_framework::coin { ): (MintRef, MintRefReceipt) acquires CoinConversionMap, PairedFungibleAssetRefs { let metadata = assert_paired_metadata_exists(); let metadata_addr = object_address(&metadata); - assert!(exists(metadata_addr), error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND)); - let mint_ref_opt = &mut borrow_global_mut(metadata_addr).mint_ref_opt; + assert!( + exists(metadata_addr), + error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND) + ); + let mint_ref_opt = + &mut borrow_global_mut(metadata_addr).mint_ref_opt; assert!(option::is_some(mint_ref_opt), error::not_found(EMINT_REF_NOT_FOUND)); (option::extract(mint_ref_opt), MintRefReceipt { metadata }) } /// Return the `MintRef` with the hot potato receipt. - public fun return_paired_mint_ref(mint_ref: MintRef, receipt: MintRefReceipt) acquires PairedFungibleAssetRefs { + public fun return_paired_mint_ref( + mint_ref: MintRef, receipt: MintRefReceipt + ) acquires PairedFungibleAssetRefs { let MintRefReceipt { metadata } = receipt; assert!( fungible_asset::mint_ref_metadata(&mint_ref) == metadata, error::invalid_argument(EMINT_REF_RECEIPT_MISMATCH) ); let metadata_addr = object_address(&metadata); - let mint_ref_opt = &mut borrow_global_mut(metadata_addr).mint_ref_opt; + let mint_ref_opt = + &mut borrow_global_mut(metadata_addr).mint_ref_opt; option::fill(mint_ref_opt, mint_ref); } @@ -469,8 +506,13 @@ module supra_framework::coin { public fun paired_transfer_ref_exists(): bool acquires CoinConversionMap, PairedFungibleAssetRefs { let metadata = assert_paired_metadata_exists(); let metadata_addr = object_address(&metadata); - assert!(exists(metadata_addr), error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND)); - option::is_some(&borrow_global(metadata_addr).transfer_ref_opt) + assert!( + exists(metadata_addr), + error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND) + ); + option::is_some( + &borrow_global(metadata_addr).transfer_ref_opt + ) } /// Get the TransferRef of paired fungible asset of a coin type from `FreezeCapability`. @@ -479,16 +521,21 @@ module supra_framework::coin { ): (TransferRef, TransferRefReceipt) acquires CoinConversionMap, PairedFungibleAssetRefs { let metadata = assert_paired_metadata_exists(); let metadata_addr = object_address(&metadata); - assert!(exists(metadata_addr), error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND)); - let transfer_ref_opt = &mut borrow_global_mut(metadata_addr).transfer_ref_opt; - assert!(option::is_some(transfer_ref_opt), error::not_found(ETRANSFER_REF_NOT_FOUND)); + assert!( + exists(metadata_addr), + error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND) + ); + let transfer_ref_opt = + &mut borrow_global_mut(metadata_addr).transfer_ref_opt; + assert!( + option::is_some(transfer_ref_opt), error::not_found(ETRANSFER_REF_NOT_FOUND) + ); (option::extract(transfer_ref_opt), TransferRefReceipt { metadata }) } /// Return the `TransferRef` with the hot potato receipt. public fun return_paired_transfer_ref( - transfer_ref: TransferRef, - receipt: TransferRefReceipt + transfer_ref: TransferRef, receipt: TransferRefReceipt ) acquires PairedFungibleAssetRefs { let TransferRefReceipt { metadata } = receipt; assert!( @@ -496,7 +543,8 @@ module supra_framework::coin { error::invalid_argument(ETRANSFER_REF_RECEIPT_MISMATCH) ); let metadata_addr = object_address(&metadata); - let transfer_ref_opt = &mut borrow_global_mut(metadata_addr).transfer_ref_opt; + let transfer_ref_opt = + &mut borrow_global_mut(metadata_addr).transfer_ref_opt; option::fill(transfer_ref_opt, transfer_ref); } @@ -505,8 +553,13 @@ module supra_framework::coin { public fun paired_burn_ref_exists(): bool acquires CoinConversionMap, PairedFungibleAssetRefs { let metadata = assert_paired_metadata_exists(); let metadata_addr = object_address(&metadata); - assert!(exists(metadata_addr), error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND)); - option::is_some(&borrow_global(metadata_addr).burn_ref_opt) + assert!( + exists(metadata_addr), + error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND) + ); + option::is_some( + &borrow_global(metadata_addr).burn_ref_opt + ) } /// Get the `BurnRef` of paired fungible asset of a coin type from `BurnCapability`. @@ -515,8 +568,12 @@ module supra_framework::coin { ): (BurnRef, BurnRefReceipt) acquires CoinConversionMap, PairedFungibleAssetRefs { let metadata = assert_paired_metadata_exists(); let metadata_addr = object_address(&metadata); - assert!(exists(metadata_addr), error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND)); - let burn_ref_opt = &mut borrow_global_mut(metadata_addr).burn_ref_opt; + assert!( + exists(metadata_addr), + error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND) + ); + let burn_ref_opt = + &mut borrow_global_mut(metadata_addr).burn_ref_opt; assert!(option::is_some(burn_ref_opt), error::not_found(EBURN_REF_NOT_FOUND)); (option::extract(burn_ref_opt), BurnRefReceipt { metadata }) } @@ -529,16 +586,19 @@ module supra_framework::coin { destroy_burn_cap(burn_cap); let metadata = assert_paired_metadata_exists(); let metadata_addr = object_address(&metadata); - assert!(exists(metadata_addr), error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND)); - let burn_ref_opt = &mut borrow_global_mut(metadata_addr).burn_ref_opt; + assert!( + exists(metadata_addr), + error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND) + ); + let burn_ref_opt = + &mut borrow_global_mut(metadata_addr).burn_ref_opt; assert!(option::is_some(burn_ref_opt), error::not_found(EBURN_REF_NOT_FOUND)); option::extract(burn_ref_opt) } /// Return the `BurnRef` with the hot potato receipt. public fun return_paired_burn_ref( - burn_ref: BurnRef, - receipt: BurnRefReceipt + burn_ref: BurnRef, receipt: BurnRefReceipt ) acquires PairedFungibleAssetRefs { let BurnRefReceipt { metadata } = receipt; assert!( @@ -546,7 +606,8 @@ module supra_framework::coin { error::invalid_argument(EBURN_REF_RECEIPT_MISMATCH) ); let metadata_addr = object_address(&metadata); - let burn_ref_opt = &mut borrow_global_mut(metadata_addr).burn_ref_opt; + let burn_ref_opt = + &mut borrow_global_mut(metadata_addr).burn_ref_opt; option::fill(burn_ref_opt, burn_ref); } @@ -555,8 +616,12 @@ module supra_framework::coin { ): &BurnRef acquires CoinConversionMap, PairedFungibleAssetRefs { let metadata = assert_paired_metadata_exists(); let metadata_addr = object_address(&metadata); - assert!(exists(metadata_addr), error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND)); - let burn_ref_opt = &mut borrow_global_mut(metadata_addr).burn_ref_opt; + assert!( + exists(metadata_addr), + error::internal(EPAIRED_FUNGIBLE_ASSET_REFS_NOT_FOUND) + ); + let burn_ref_opt = + &mut borrow_global_mut(metadata_addr).burn_ref_opt; assert!(option::is_some(burn_ref_opt), error::not_found(EBURN_REF_NOT_FOUND)); option::borrow(burn_ref_opt) } @@ -573,9 +638,12 @@ module supra_framework::coin { /// This should be called by on-chain governance to update the config and allow /// or disallow upgradability of total supply. - public fun allow_supply_upgrades(supra_framework: &signer, allowed: bool) acquires SupplyConfig { + public fun allow_supply_upgrades( + supra_framework: &signer, allowed: bool + ) acquires SupplyConfig { system_addresses::assert_supra_framework(supra_framework); - let allow_upgrades = &mut borrow_global_mut(@supra_framework).allow_upgrades; + let allow_upgrades = + &mut borrow_global_mut(@supra_framework).allow_upgrades; *allow_upgrades = allowed; } @@ -585,27 +653,33 @@ module supra_framework::coin { /// Creates a new aggregatable coin with value overflowing on `limit`. Note that this function can /// only be called by Supra Framework (0x1) account for now because of `create_aggregator`. - public(friend) fun initialize_aggregatable_coin(supra_framework: &signer): AggregatableCoin { + public(friend) fun initialize_aggregatable_coin( + supra_framework: &signer + ): AggregatableCoin { let aggregator = aggregator_factory::create_aggregator(supra_framework, MAX_U64); - AggregatableCoin { - value: aggregator, - } - } + AggregatableCoin { value: aggregator } + } /// Returns true if the value of aggregatable coin is zero. - public(friend) fun is_aggregatable_coin_zero(coin: &AggregatableCoin): bool { + public(friend) fun is_aggregatable_coin_zero( + coin: &AggregatableCoin + ): bool { let amount = aggregator::read(&coin.value); amount == 0 } /// Drains the aggregatable coin, setting it to zero and returning a standard coin. - public(friend) fun drain_aggregatable_coin(coin: &mut AggregatableCoin): Coin { + public(friend) fun drain_aggregatable_coin( + coin: &mut AggregatableCoin + ): Coin { spec { // TODO: The data invariant is not properly assumed from CollectedFeesPerBlock. assume aggregator::spec_get_limit(coin.value) == MAX_U64; }; let amount = aggregator::read(&coin.value); - assert!(amount <= MAX_U64, error::out_of_range(EAGGREGATABLE_COIN_VALUE_TOO_LARGE)); + assert!( + amount <= MAX_U64, error::out_of_range(EAGGREGATABLE_COIN_VALUE_TOO_LARGE) + ); spec { update aggregate_supply = aggregate_supply - amount; }; @@ -613,13 +687,13 @@ module supra_framework::coin { spec { update supply = supply + amount; }; - Coin { - value: (amount as u64), - } + Coin { value: (amount as u64) } } /// Merges `coin` into aggregatable coin (`dst_coin`). - public(friend) fun merge_aggregatable_coin(dst_coin: &mut AggregatableCoin, coin: Coin) { + public(friend) fun merge_aggregatable_coin( + dst_coin: &mut AggregatableCoin, coin: Coin + ) { spec { update supply = supply - coin.value; }; @@ -635,28 +709,26 @@ module supra_framework::coin { public(friend) fun collect_into_aggregatable_coin( account_addr: address, amount: u64, - dst_coin: &mut AggregatableCoin, + dst_coin: &mut AggregatableCoin ) acquires CoinStore, CoinConversionMap, CoinInfo, PairedCoinType { // Skip collecting if amount is zero. - if (amount == 0) { - return - }; + if (amount == 0) { return }; - let (coin_amount_to_collect, fa_amount_to_collect) = calculate_amount_to_withdraw( - account_addr, - amount - ); - let coin = if (coin_amount_to_collect > 0) { - let coin_store = borrow_global_mut>(account_addr); - extract(&mut coin_store.coin, coin_amount_to_collect) - } else { - zero() - }; - if (fa_amount_to_collect > 0) { - let store_addr = primary_fungible_store::primary_store_address( - account_addr, - option::destroy_some(paired_metadata()) + let (coin_amount_to_collect, fa_amount_to_collect) = + calculate_amount_to_withdraw( + account_addr, amount ); + let coin = + if (coin_amount_to_collect > 0) { + let coin_store = borrow_global_mut>(account_addr); + extract(&mut coin_store.coin, coin_amount_to_collect) + } else { zero() }; + if (fa_amount_to_collect > 0) { + let store_addr = + primary_fungible_store::primary_store_address( + account_addr, + option::destroy_some(paired_metadata()) + ); let fa = fungible_asset::withdraw_internal(store_addr, fa_amount_to_collect); merge(&mut coin, fungible_asset_to_coin(fa)); }; @@ -664,44 +736,51 @@ module supra_framework::coin { } inline fun calculate_amount_to_withdraw( - account_addr: address, - amount: u64 + account_addr: address, amount: u64 ): (u64, u64) { let coin_balance = coin_balance(account_addr); if (coin_balance >= amount) { (amount, 0) } else { let metadata = paired_metadata(); - if (option::is_some(&metadata) && primary_fungible_store::primary_store_exists( - account_addr, - option::destroy_some(metadata) - )) + if (option::is_some(&metadata) + && primary_fungible_store::primary_store_exists( + account_addr, + option::destroy_some(metadata) + )) (coin_balance, amount - coin_balance) - else - abort error::invalid_argument(EINSUFFICIENT_BALANCE) + else abort error::invalid_argument(EINSUFFICIENT_BALANCE) } } - fun maybe_convert_to_fungible_store(account: address) acquires CoinStore, CoinConversionMap, CoinInfo { + fun maybe_convert_to_fungible_store( + account: address + ) acquires CoinStore, CoinConversionMap, CoinInfo { if (!features::coin_to_fungible_asset_migration_feature_enabled()) { abort error::unavailable(ECOIN_TO_FUNGIBLE_ASSET_FEATURE_NOT_ENABLED) }; - assert!(is_coin_initialized(), error::invalid_argument(ECOIN_INFO_NOT_PUBLISHED)); + assert!( + is_coin_initialized(), + error::invalid_argument(ECOIN_INFO_NOT_PUBLISHED) + ); let metadata = ensure_paired_metadata(); let store = primary_fungible_store::ensure_primary_store_exists(account, metadata); let store_address = object::object_address(&store); if (exists>(account)) { - let CoinStore { coin, frozen, deposit_events, withdraw_events } = move_from>( - account - ); + let CoinStore { coin, frozen, deposit_events, withdraw_events } = + move_from>(account); event::emit( CoinEventHandleDeletion { event_handle_creation_address: guid::creator_address( event::guid(&deposit_events) ), - deleted_deposit_event_handle_creation_number: guid::creation_num(event::guid(&deposit_events)), - deleted_withdraw_event_handle_creation_number: guid::creation_num(event::guid(&withdraw_events)) + deleted_deposit_event_handle_creation_number: guid::creation_num( + event::guid(&deposit_events) + ), + deleted_withdraw_event_handle_creation_number: guid::creation_num( + event::guid(&withdraw_events) + ) } ); event::destroy_handle(deposit_events); @@ -761,17 +840,20 @@ module supra_framework::coin { /// Returns the balance of `owner` for provided `CoinType` and its paired FA if exists. public fun balance(owner: address): u64 acquires CoinConversionMap, CoinStore { let paired_metadata = paired_metadata(); - coin_balance(owner) + if (option::is_some(&paired_metadata)) { - primary_fungible_store::balance( - owner, - option::extract(&mut paired_metadata) - ) - } else { 0 } + coin_balance(owner) + + if (option::is_some(&paired_metadata)) { + primary_fungible_store::balance( + owner, + option::extract(&mut paired_metadata) + ) + } else { 0 } } #[view] /// Returns whether the balance of `owner` for provided `CoinType` and its paired FA is >= `amount`. - public fun is_balance_at_least(owner: address, amount: u64): bool acquires CoinConversionMap, CoinStore { + public fun is_balance_at_least( + owner: address, amount: u64 + ): bool acquires CoinConversionMap, CoinStore { let coin_balance = coin_balance(owner); if (coin_balance >= amount) { return true @@ -791,9 +873,7 @@ module supra_framework::coin { inline fun coin_balance(owner: address): u64 { if (exists>(owner)) { borrow_global>(owner).coin.value - } else { - 0 - } + } else { 0 } } #[view] @@ -817,15 +897,22 @@ module supra_framework::coin { #[view] /// Returns `true` if `account_addr` is registered to receive `CoinType`. - public fun is_account_registered(account_addr: address): bool acquires CoinConversionMap { - assert!(is_coin_initialized(), error::invalid_argument(ECOIN_INFO_NOT_PUBLISHED)); - if (exists>(account_addr)) { - true - } else { + public fun is_account_registered( + account_addr: address + ): bool acquires CoinConversionMap { + assert!( + is_coin_initialized(), + error::invalid_argument(ECOIN_INFO_NOT_PUBLISHED) + ); + if (exists>(account_addr)) { true } + else { let paired_metadata_opt = paired_metadata(); - (option::is_some( - &paired_metadata_opt - ) && migrated_primary_fungible_store_exists(account_addr, option::destroy_some(paired_metadata_opt))) + ( + option::is_some(&paired_metadata_opt) + && migrated_primary_fungible_store_exists( + account_addr, option::destroy_some(paired_metadata_opt) + ) + ) } } @@ -855,7 +942,8 @@ module supra_framework::coin { let coin_supply = coin_supply(); let metadata = paired_metadata(); if (option::is_some(&metadata)) { - let fungible_asset_supply = fungible_asset::supply(option::extract(&mut metadata)); + let fungible_asset_supply = + fungible_asset::supply(option::extract(&mut metadata)); if (option::is_some(&coin_supply)) { let supply = option::borrow_mut(&mut coin_supply); *supply = *supply + option::destroy_some(fungible_asset_supply); @@ -867,7 +955,8 @@ module supra_framework::coin { #[view] /// Returns the amount of coin in existence. public fun coin_supply(): Option acquires CoinInfo { - let maybe_supply = &borrow_global>(coin_address()).supply; + let maybe_supply = + &borrow_global>(coin_address()).supply; if (option::is_some(maybe_supply)) { // We do track supply, in this case read from optional aggregator. let supply = option::borrow(maybe_supply); @@ -877,13 +966,16 @@ module supra_framework::coin { option::none() } } + // // Public functions // /// Burn `coin` with capability. /// The capability `_cap` should be passed as a reference to `BurnCapability`. - public fun burn(coin: Coin, _cap: &BurnCapability) acquires CoinInfo { + public fun burn( + coin: Coin, _cap: &BurnCapability + ) acquires CoinInfo { burn_internal(coin); } @@ -895,17 +987,15 @@ module supra_framework::coin { public fun burn_from( account_addr: address, amount: u64, - burn_cap: &BurnCapability, + burn_cap: &BurnCapability ) acquires CoinInfo, CoinStore, CoinConversionMap, PairedFungibleAssetRefs { // Skip burning if amount is zero. This shouldn't error out as it's called as part of transaction fee burning. - if (amount == 0) { - return - }; + if (amount == 0) { return }; - let (coin_amount_to_burn, fa_amount_to_burn) = calculate_amount_to_withdraw( - account_addr, - amount - ); + let (coin_amount_to_burn, fa_amount_to_burn) = + calculate_amount_to_withdraw( + account_addr, amount + ); if (coin_amount_to_burn > 0) { let coin_store = borrow_global_mut>(account_addr); let coin_to_burn = extract(&mut coin_store.coin, coin_amount_to_burn); @@ -914,7 +1004,9 @@ module supra_framework::coin { if (fa_amount_to_burn > 0) { fungible_asset::burn_from( borrow_paired_burn_ref(burn_cap), - primary_fungible_store::primary_store(account_addr, option::destroy_some(paired_metadata())), + primary_fungible_store::primary_store( + account_addr, option::destroy_some(paired_metadata()) + ), fa_amount_to_burn ); }; @@ -922,32 +1014,38 @@ module supra_framework::coin { /// Deposit the coin balance into the recipient's account and emit an event. public fun deposit( - account_addr: address, - coin: Coin + account_addr: address, coin: Coin ) acquires CoinStore, CoinConversionMap, CoinInfo { if (exists>(account_addr)) { let coin_store = borrow_global_mut>(account_addr); assert!( !coin_store.frozen, - error::permission_denied(EFROZEN), + error::permission_denied(EFROZEN) ); if (std::features::module_event_migration_enabled()) { event::emit( - CoinDeposit { coin_type: type_name(), account: account_addr, amount: coin.value } + CoinDeposit { + coin_type: type_name(), + account: account_addr, + amount: coin.value + } ); }; event::emit_event( &mut coin_store.deposit_events, - DepositEvent { amount: coin.value }, + DepositEvent { amount: coin.value } ); merge(&mut coin_store.coin, coin); } else { let metadata = paired_metadata(); - if (option::is_some(&metadata) && migrated_primary_fungible_store_exists( - account_addr, - option::destroy_some(metadata) - )) { - primary_fungible_store::deposit(account_addr, coin_to_fungible_asset_internal(coin)); + if (option::is_some(&metadata) + && migrated_primary_fungible_store_exists( + account_addr, + option::destroy_some(metadata) + )) { + primary_fungible_store::deposit( + account_addr, coin_to_fungible_asset_internal(coin) + ); } else { abort error::not_found(ECOIN_STORE_NOT_PUBLISHED) }; @@ -955,31 +1053,35 @@ module supra_framework::coin { } inline fun migrated_primary_fungible_store_exists( - account_address: address, - metadata: Object + account_address: address, metadata: Object ): bool { - let primary_store_address = primary_fungible_store::primary_store_address(account_address, metadata); - fungible_asset::store_exists(primary_store_address) && ( - // migration flag is needed, until we start defaulting new accounts to SUPRA PFS - features::new_accounts_default_to_fa_supra_store_enabled() || exists(primary_store_address) - ) + let primary_store_address = + primary_fungible_store::primary_store_address( + account_address, metadata + ); + fungible_asset::store_exists(primary_store_address) + && ( + // migration flag is needed, until we start defaulting new accounts to SUPRA PFS + features::new_accounts_default_to_fa_supra_store_enabled() + || exists(primary_store_address) + ) } /// Deposit the coin balance into the recipient's account without checking if the account is frozen. /// This is for internal use only and doesn't emit an DepositEvent. public(friend) fun force_deposit( - account_addr: address, - coin: Coin + account_addr: address, coin: Coin ) acquires CoinStore, CoinConversionMap, CoinInfo { if (exists>(account_addr)) { let coin_store = borrow_global_mut>(account_addr); merge(&mut coin_store.coin, coin); } else { let metadata = paired_metadata(); - if (option::is_some(&metadata) && migrated_primary_fungible_store_exists( - account_addr, - option::destroy_some(metadata) - )) { + if (option::is_some(&metadata) + && migrated_primary_fungible_store_exists( + account_addr, + option::destroy_some(metadata) + )) { let fa = coin_to_fungible_asset_internal(coin); let metadata = fungible_asset::asset_metadata(&fa); let store = primary_fungible_store::primary_store(account_addr, metadata); @@ -1030,8 +1132,7 @@ module supra_framework::coin { #[legacy_entry_fun] /// Freeze a CoinStore to prevent transfers public entry fun freeze_coin_store( - account_addr: address, - _freeze_cap: &FreezeCapability, + account_addr: address, _freeze_cap: &FreezeCapability ) acquires CoinStore { let coin_store = borrow_global_mut>(account_addr); coin_store.frozen = true; @@ -1040,8 +1141,7 @@ module supra_framework::coin { #[legacy_entry_fun] /// Unfreeze a CoinStore to allow transfers public entry fun unfreeze_coin_store( - account_addr: address, - _freeze_cap: &FreezeCapability, + account_addr: address, _freeze_cap: &FreezeCapability ) acquires CoinStore { let coin_store = borrow_global_mut>(account_addr); coin_store.frozen = false; @@ -1055,7 +1155,7 @@ module supra_framework::coin { // Only coin creators can upgrade total supply. assert!( coin_address() == account_addr, - error::invalid_argument(ECOIN_INFO_ADDRESS_MISMATCH), + error::invalid_argument(ECOIN_INFO_ADDRESS_MISMATCH) ); // Can only succeed once on-chain governance agreed on the upgrade. @@ -1083,7 +1183,7 @@ module supra_framework::coin { name: string::String, symbol: string::String, decimals: u8, - monitor_supply: bool, + monitor_supply: bool ): (BurnCapability, FreezeCapability, MintCapability) { initialize_internal(account, name, symbol, decimals, monitor_supply, false) } @@ -1094,22 +1194,24 @@ module supra_framework::coin { name: string::String, symbol: string::String, decimals: u8, - monitor_supply: bool, + monitor_supply: bool ): (BurnCapability, FreezeCapability, MintCapability) { system_addresses::assert_supra_framework(account); initialize_internal(account, name, symbol, decimals, monitor_supply, true) } - + public(friend) fun initialize_with_parallelizable_supply_with_limit( account: &signer, name: string::String, symbol: string::String, decimals: u8, monitor_supply: bool, - limit: u128, + limit: u128 ): (BurnCapability, FreezeCapability, MintCapability) { system_addresses::assert_supra_framework(account); - initialize_internal_with_limit(account, name, symbol, decimals, monitor_supply, true, limit) + initialize_internal_with_limit( + account, name, symbol, decimals, monitor_supply, true, limit + ) } fun initialize_internal( @@ -1118,73 +1220,102 @@ module supra_framework::coin { symbol: string::String, decimals: u8, monitor_supply: bool, - parallelizable: bool, + parallelizable: bool ): (BurnCapability, FreezeCapability, MintCapability) { let account_addr = signer::address_of(account); assert!( coin_address() == account_addr, - error::invalid_argument(ECOIN_INFO_ADDRESS_MISMATCH), + error::invalid_argument(ECOIN_INFO_ADDRESS_MISMATCH) ); assert!( !exists>(account_addr), - error::already_exists(ECOIN_INFO_ALREADY_PUBLISHED), + error::already_exists(ECOIN_INFO_ALREADY_PUBLISHED) ); - assert!(string::length(&name) <= MAX_COIN_NAME_LENGTH, error::invalid_argument(ECOIN_NAME_TOO_LONG)); - assert!(string::length(&symbol) <= MAX_COIN_SYMBOL_LENGTH, error::invalid_argument(ECOIN_SYMBOL_TOO_LONG)); + assert!( + string::length(&name) <= MAX_COIN_NAME_LENGTH, + error::invalid_argument(ECOIN_NAME_TOO_LONG) + ); + assert!( + string::length(&symbol) <= MAX_COIN_SYMBOL_LENGTH, + error::invalid_argument(ECOIN_SYMBOL_TOO_LONG) + ); let coin_info = CoinInfo { name, symbol, decimals, - supply: if (monitor_supply) { option::some(optional_aggregator::new(MAX_U128, parallelizable)) } else { option::none() }, + supply: if (monitor_supply) { + option::some(optional_aggregator::new(MAX_U128, parallelizable)) + } else { + option::none() + } }; move_to(account, coin_info); - (BurnCapability {}, FreezeCapability {}, MintCapability {}) + ( + BurnCapability {}, + FreezeCapability {}, + MintCapability {} + ) } - fun initialize_internal_with_limit( + fun initialize_internal_with_limit( account: &signer, name: string::String, symbol: string::String, decimals: u8, monitor_supply: bool, parallelizable: bool, - limit: u128, + limit: u128 ): (BurnCapability, FreezeCapability, MintCapability) { let account_addr = signer::address_of(account); assert!( coin_address() == account_addr, - error::invalid_argument(ECOIN_INFO_ADDRESS_MISMATCH), + error::invalid_argument(ECOIN_INFO_ADDRESS_MISMATCH) ); assert!( !exists>(account_addr), - error::already_exists(ECOIN_INFO_ALREADY_PUBLISHED), + error::already_exists(ECOIN_INFO_ALREADY_PUBLISHED) ); - assert!(string::length(&name) <= MAX_COIN_NAME_LENGTH, error::invalid_argument(ECOIN_NAME_TOO_LONG)); - assert!(string::length(&symbol) <= MAX_COIN_SYMBOL_LENGTH, error::invalid_argument(ECOIN_SYMBOL_TOO_LONG)); + assert!( + string::length(&name) <= MAX_COIN_NAME_LENGTH, + error::invalid_argument(ECOIN_NAME_TOO_LONG) + ); + assert!( + string::length(&symbol) <= MAX_COIN_SYMBOL_LENGTH, + error::invalid_argument(ECOIN_SYMBOL_TOO_LONG) + ); let coin_info = CoinInfo { name, symbol, decimals, - supply: if (monitor_supply) { option::some(optional_aggregator::new(limit, parallelizable)) } else { option::none() }, + supply: if (monitor_supply) { + option::some(optional_aggregator::new(limit, parallelizable)) + } else { + option::none() + } }; move_to(account, coin_info); - (BurnCapability {}, FreezeCapability {}, MintCapability {}) + ( + BurnCapability {}, + FreezeCapability {}, + MintCapability {} + ) } - /// "Merges" the two given coins. The coin passed in as `dst_coin` will have a value equal /// to the sum of the two tokens (`dst_coin` and `source_coin`). - public fun merge(dst_coin: &mut Coin, source_coin: Coin) { + public fun merge( + dst_coin: &mut Coin, source_coin: Coin + ) { spec { assume dst_coin.value + source_coin.value <= MAX_U64; }; @@ -1202,8 +1333,7 @@ module supra_framework::coin { /// The capability `_cap` should be passed as reference to `MintCapability`. /// Returns minted `Coin`. public fun mint( - amount: u64, - _cap: &MintCapability, + amount: u64, _cap: &MintCapability ): Coin acquires CoinInfo { mint_internal(amount) } @@ -1211,16 +1341,14 @@ module supra_framework::coin { public fun register(account: &signer) acquires CoinConversionMap { let account_addr = signer::address_of(account); // Short-circuit and do nothing if account is already registered for CoinType. - if (is_account_registered(account_addr)) { - return - }; + if (is_account_registered(account_addr)) { return }; account::register_coin(account_addr); let coin_store = CoinStore { coin: Coin { value: 0 }, frozen: false, deposit_events: account::new_event_handle(account), - withdraw_events: account::new_event_handle(account), + withdraw_events: account::new_event_handle(account) }; move_to(account, coin_store); } @@ -1229,7 +1357,7 @@ module supra_framework::coin { public entry fun transfer( from: &signer, to: address, - amount: u64, + amount: u64 ) acquires CoinStore, CoinConversionMap, CoinInfo, PairedCoinType { let coin = withdraw(from, amount); deposit(to, coin); @@ -1242,42 +1370,43 @@ module supra_framework::coin { /// Withdraw specified `amount` of coin `CoinType` from the signing account. public fun withdraw( - account: &signer, - amount: u64, + account: &signer, amount: u64 ): Coin acquires CoinStore, CoinConversionMap, CoinInfo, PairedCoinType { let account_addr = signer::address_of(account); - let (coin_amount_to_withdraw, fa_amount_to_withdraw) = calculate_amount_to_withdraw( - account_addr, - amount - ); - let withdrawn_coin = if (coin_amount_to_withdraw > 0) { - let coin_store = borrow_global_mut>(account_addr); - assert!( - !coin_store.frozen, - error::permission_denied(EFROZEN), + let (coin_amount_to_withdraw, fa_amount_to_withdraw) = + calculate_amount_to_withdraw( + account_addr, amount ); - if (std::features::module_event_migration_enabled()) { - event::emit( - CoinWithdraw { - coin_type: type_name(), account: account_addr, amount: coin_amount_to_withdraw - } + let withdrawn_coin = + if (coin_amount_to_withdraw > 0) { + let coin_store = borrow_global_mut>(account_addr); + assert!( + !coin_store.frozen, + error::permission_denied(EFROZEN) ); - }; - event::emit_event( - &mut coin_store.withdraw_events, - WithdrawEvent { amount: coin_amount_to_withdraw }, - ); - extract(&mut coin_store.coin, coin_amount_to_withdraw) - } else { - zero() - }; + if (std::features::module_event_migration_enabled()) { + event::emit( + CoinWithdraw { + coin_type: type_name(), + account: account_addr, + amount: coin_amount_to_withdraw + } + ); + }; + event::emit_event( + &mut coin_store.withdraw_events, + WithdrawEvent { amount: coin_amount_to_withdraw } + ); + extract(&mut coin_store.coin, coin_amount_to_withdraw) + } else { zero() }; if (fa_amount_to_withdraw > 0) { - let fa = primary_fungible_store::withdraw( - account, - option::destroy_some(paired_metadata()), - fa_amount_to_withdraw - ); + let fa = + primary_fungible_store::withdraw( + account, + option::destroy_some(paired_metadata()), + fa_amount_to_withdraw + ); merge(&mut withdrawn_coin, fungible_asset_to_coin(fa)); }; withdrawn_coin @@ -1288,45 +1417,56 @@ module supra_framework::coin { spec { update supply = supply + 0; }; - Coin { - value: 0 - } + Coin { value: 0 } } /// Destroy a freeze capability. Freeze capability is dangerous and therefore should be destroyed if not used. - public fun destroy_freeze_cap(freeze_cap: FreezeCapability) { + public fun destroy_freeze_cap( + freeze_cap: FreezeCapability + ) { let FreezeCapability {} = freeze_cap; } /// Destroy a mint capability. - public fun destroy_mint_cap(mint_cap: MintCapability) { + public fun destroy_mint_cap( + mint_cap: MintCapability + ) { let MintCapability {} = mint_cap; } /// Destroy a burn capability. - public fun destroy_burn_cap(burn_cap: BurnCapability) { + public fun destroy_burn_cap( + burn_cap: BurnCapability + ) { let BurnCapability {} = burn_cap; } fun mint_internal(amount: u64): Coin acquires CoinInfo { if (amount == 0) { - return Coin { - value: 0 - } + return Coin { value: 0 } }; - let maybe_supply = &mut borrow_global_mut>(coin_address()).supply; + let maybe_supply = + &mut borrow_global_mut>(coin_address()).supply; if (option::is_some(maybe_supply)) { let supply = option::borrow_mut(maybe_supply); spec { use supra_framework::optional_aggregator; use supra_framework::aggregator; - assume optional_aggregator::is_parallelizable(supply) ==> (aggregator::spec_aggregator_get_val( - option::borrow(supply.aggregator) - ) - + amount <= aggregator::spec_get_limit(option::borrow(supply.aggregator))); + assume optional_aggregator::is_parallelizable(supply) ==> + ( + aggregator::spec_aggregator_get_val( + option::borrow(supply.aggregator) + ) + amount + <= aggregator::spec_get_limit( + option::borrow(supply.aggregator) + ) + ); assume !optional_aggregator::is_parallelizable(supply) ==> - (option::borrow(supply.integer).value + amount <= option::borrow(supply.integer).limit); + ( + option::borrow(supply.integer).value + amount + <= option::borrow(supply.integer).limit + ); }; optional_aggregator::add(supply, (amount as u128)); }; @@ -1342,7 +1482,8 @@ module supra_framework::coin { }; let Coin { value: amount } = coin; if (amount != 0) { - let maybe_supply = &mut borrow_global_mut>(coin_address()).supply; + let maybe_supply = + &mut borrow_global_mut>(coin_address()).supply; if (option::is_some(maybe_supply)) { let supply = option::borrow_mut(maybe_supply); optional_aggregator::sub(supply, (amount as u128)); @@ -1358,25 +1499,28 @@ module supra_framework::coin { struct FakeMoneyCapabilities has key { burn_cap: BurnCapability, freeze_cap: FreezeCapability, - mint_cap: MintCapability, + mint_cap: MintCapability } #[test_only] struct FakeMoneyRefs has key { mint_ref: MintRef, transfer_ref: TransferRef, - burn_ref: BurnRef, + burn_ref: BurnRef } #[test_only] fun create_coin_store(account: &signer) { - assert!(is_coin_initialized(), error::invalid_argument(ECOIN_INFO_NOT_PUBLISHED)); + assert!( + is_coin_initialized(), + error::invalid_argument(ECOIN_INFO_NOT_PUBLISHED) + ); if (!exists>(signer::address_of(account))) { let coin_store = CoinStore { coin: Coin { value: 0 }, frozen: false, deposit_events: account::new_event_handle(account), - withdraw_events: account::new_event_handle(account), + withdraw_events: account::new_event_handle(account) }; move_to(account, coin_store); } @@ -1391,7 +1535,7 @@ module supra_framework::coin { fun initialize_fake_money( account: &signer, decimals: u8, - monitor_supply: bool, + monitor_supply: bool ): (BurnCapability, FreezeCapability, MintCapability) { aggregator_factory::initialize_aggregator_factory_for_test(account); initialize( @@ -1407,13 +1551,14 @@ module supra_framework::coin { public fun initialize_and_register_fake_money( account: &signer, decimals: u8, - monitor_supply: bool, + monitor_supply: bool ): (BurnCapability, FreezeCapability, MintCapability) { - let (burn_cap, freeze_cap, mint_cap) = initialize_fake_money( - account, - decimals, - monitor_supply - ); + let (burn_cap, freeze_cap, mint_cap) = + initialize_fake_money( + account, + decimals, + monitor_supply + ); create_coin_store(account); create_coin_conversion_map(account); (burn_cap, freeze_cap, mint_cap) @@ -1421,26 +1566,23 @@ module supra_framework::coin { #[test_only] public entry fun create_fake_money( - source: &signer, - destination: &signer, - amount: u64 + source: &signer, destination: &signer, amount: u64 ) acquires CoinInfo, CoinStore, CoinConversionMap { - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(source, 18, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(source, 18, true); create_coin_store(destination); let coins_minted = mint(amount, &mint_cap); deposit(signer::address_of(source), coins_minted); - move_to(source, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + source, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(source = @0x1, destination = @0x2)] public entry fun end_to_end( - source: signer, - destination: signer, + source: signer, destination: signer ) acquires CoinInfo, CoinStore, CoinConversionMap, PairedCoinType { let source_addr = signer::address_of(&source); account::create_account_for_test(source_addr); @@ -1450,11 +1592,10 @@ module supra_framework::coin { let name = string::utf8(b"Fake money"); let symbol = string::utf8(b"FMD"); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money( - &source, - 18, - true - ); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money( + &source, 18, true + ); register(&source); register(&destination); assert!(*option::borrow(&supply()) == 0, 0); @@ -1482,24 +1623,23 @@ module supra_framework::coin { burn(coin, &burn_cap); assert!(*option::borrow(&supply()) == 90, 8); - move_to(&source, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &source, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(source = @0x1, destination = @0x2)] public entry fun end_to_end_no_supply( - source: signer, - destination: signer, + source: signer, destination: signer ) acquires CoinInfo, CoinStore, CoinConversionMap, PairedCoinType { let source_addr = signer::address_of(&source); account::create_account_for_test(source_addr); let destination_addr = signer::address_of(&destination); account::create_account_for_test(destination_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&source, 1, false); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&source, 1, false); register(&destination); assert!(option::is_none(&supply()), 0); @@ -1516,43 +1656,42 @@ module supra_framework::coin { burn(coin, &burn_cap); assert!(option::is_none(&supply()), 4); - move_to(&source, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &source, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(source = @0x2, framework = @supra_framework)] #[expected_failure(abort_code = 0x10001, location = Self)] public fun fail_initialize(source: signer, framework: signer) { aggregator_factory::initialize_aggregator_factory_for_test(&framework); - let (burn_cap, freeze_cap, mint_cap) = initialize( + let (burn_cap, freeze_cap, mint_cap) = + initialize( + &source, + string::utf8(b"Fake money"), + string::utf8(b"FMD"), + 1, + true + ); + + move_to( &source, - string::utf8(b"Fake money"), - string::utf8(b"FMD"), - 1, - true, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } ); - - move_to(&source, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); } #[test(source = @0x1, destination = @0x2)] public entry fun transfer_to_migrated_destination( - source: signer, - destination: signer, + source: signer, destination: signer ) acquires CoinInfo, CoinStore, CoinConversionMap, PairedCoinType { let source_addr = signer::address_of(&source); account::create_account_for_test(source_addr); let destination_addr = signer::address_of(&destination); account::create_account_for_test(destination_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&source, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&source, 1, true); assert!(*option::borrow(&supply()) == 0, 0); let coins_minted = mint(100, &mint_cap); @@ -1564,20 +1703,20 @@ module supra_framework::coin { assert!(balance(destination_addr) == 50, 2); assert!(!coin_store_exists(destination_addr), 0); - move_to(&source, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &source, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(source = @0x1)] public entry fun test_burn_from_with_capability( - source: signer, + source: signer ) acquires CoinInfo, CoinStore, CoinConversionMap, PairedFungibleAssetRefs { let source_addr = signer::address_of(&source); account::create_account_for_test(source_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&source, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&source, 1, true); let coins_minted = mint(100, &mint_cap); deposit(source_addr, coins_minted); @@ -1592,12 +1731,22 @@ module supra_framework::coin { // Burn coin and fa with both stores burn_from(source_addr, 100, &burn_cap); assert!(balance(source_addr) == 150, 0); - assert!(primary_fungible_store::balance(source_addr, ensure_paired_metadata()) == 150, 0); + assert!( + primary_fungible_store::balance( + source_addr, ensure_paired_metadata() + ) == 150, + 0 + ); // Burn fa only with both stores burn_from(source_addr, 100, &burn_cap); assert!(balance(source_addr) == 50, 0); - assert!(primary_fungible_store::balance(source_addr, ensure_paired_metadata()) == 50, 0); + assert!( + primary_fungible_store::balance( + source_addr, ensure_paired_metadata() + ) == 50, + 0 + ); // Burn fa only with only fungible store let coins_minted = mint(50, &mint_cap); @@ -1611,37 +1760,33 @@ module supra_framework::coin { assert!(balance(source_addr) == 90, 2); assert!(*option::borrow(&supply()) == 90, 3); - move_to(&source, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &source, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(source = @0x1)] #[expected_failure(abort_code = 0x10007, location = Self)] - public fun test_destroy_non_zero( - source: signer, - ) acquires CoinInfo { + public fun test_destroy_non_zero(source: signer) acquires CoinInfo { account::create_account_for_test(signer::address_of(&source)); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&source, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&source, 1, true); let coins_minted = mint(100, &mint_cap); destroy_zero(coins_minted); - move_to(&source, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &source, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(source = @0x1)] - public entry fun test_extract( - source: signer, - ) acquires CoinInfo, CoinStore, CoinConversionMap { + public entry fun test_extract(source: signer) acquires CoinInfo, CoinStore, CoinConversionMap { let source_addr = signer::address_of(&source); account::create_account_for_test(source_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&source, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&source, 1, true); let coins_minted = mint(100, &mint_cap); @@ -1654,11 +1799,10 @@ module supra_framework::coin { assert!(balance(source_addr) == 100, 2); - move_to(&source, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &source, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(source = @0x1)] @@ -1668,28 +1812,29 @@ module supra_framework::coin { let (burn_cap, freeze_cap, mint_cap) = initialize_fake_money(&source, 1, true); assert!(is_coin_initialized(), 1); - move_to(&source, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &source, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @0x1)] - public fun test_is_coin_store_frozen(account: signer) acquires CoinStore, CoinConversionMap, CoinInfo { + public fun test_is_coin_store_frozen( + account: signer + ) acquires CoinStore, CoinConversionMap, CoinInfo { let account_addr = signer::address_of(&account); account::create_account_for_test(account_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&account, 18, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&account, 18, true); assert!(coin_store_exists(account_addr), 1); assert!(!is_coin_store_frozen(account_addr), 1); maybe_convert_to_fungible_store(account_addr); assert!(!coin_store_exists(account_addr), 1); - move_to(&account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test] @@ -1705,7 +1850,8 @@ module supra_framework::coin { ) acquires CoinInfo, CoinStore, CoinConversionMap, PairedFungibleAssetRefs { let account_addr = signer::address_of(&account); account::create_account_for_test(account_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&account, 18, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&account, 18, true); let coins_minted = mint(100, &mint_cap); deposit(account_addr, coins_minted); @@ -1713,22 +1859,34 @@ module supra_framework::coin { freeze_coin_store(account_addr, &freeze_cap); burn_from(account_addr, 90, &burn_cap); maybe_convert_to_fungible_store(account_addr); - assert!(primary_fungible_store::is_frozen(account_addr, ensure_paired_metadata()), 1); - assert!(primary_fungible_store::balance(account_addr, ensure_paired_metadata()) == 10, 1); + assert!( + primary_fungible_store::is_frozen( + account_addr, ensure_paired_metadata() + ), + 1 + ); + assert!( + primary_fungible_store::balance( + account_addr, ensure_paired_metadata() + ) == 10, + 1 + ); - move_to(&account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @0x1)] #[expected_failure(abort_code = 0x50003, location = supra_framework::fungible_asset)] - public entry fun withdraw_frozen(account: signer) acquires CoinInfo, CoinStore, CoinConversionMap, PairedCoinType { + public entry fun withdraw_frozen( + account: signer + ) acquires CoinInfo, CoinStore, CoinConversionMap, PairedCoinType { let account_addr = signer::address_of(&account); account::create_account_for_test(account_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&account, 18, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&account, 18, true); let coins_minted = mint(100, &mint_cap); deposit(account_addr, coins_minted); @@ -1737,11 +1895,10 @@ module supra_framework::coin { let coin = withdraw(&account, 90); burn(coin, &burn_cap); - move_to(&account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @0x1)] @@ -1749,17 +1906,17 @@ module supra_framework::coin { public entry fun deposit_frozen(account: signer) acquires CoinInfo, CoinStore, CoinConversionMap { let account_addr = signer::address_of(&account); account::create_account_for_test(account_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&account, 18, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&account, 18, true); let coins_minted = mint(100, &mint_cap); freeze_coin_store(account_addr, &freeze_cap); deposit(account_addr, coins_minted); - move_to(&account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @0x1)] @@ -1768,7 +1925,8 @@ module supra_framework::coin { ) acquires CoinInfo, CoinStore, CoinConversionMap, PairedCoinType { let account_addr = signer::address_of(&account); account::create_account_for_test(account_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&account, 18, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&account, 18, true); let coins_minted = mint(100, &mint_cap); freeze_coin_store(account_addr, &freeze_cap); @@ -1780,46 +1938,44 @@ module supra_framework::coin { let coin = withdraw(&account, 10); burn(coin, &burn_cap); - move_to(&account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test_only] fun initialize_with_aggregator(account: &signer) { - let (burn_cap, freeze_cap, mint_cap) = initialize_with_parallelizable_supply( + let (burn_cap, freeze_cap, mint_cap) = + initialize_with_parallelizable_supply( + account, + string::utf8(b"Fake money"), + string::utf8(b"FMD"), + 1, + true + ); + move_to( account, - string::utf8(b"Fake money"), - string::utf8(b"FMD"), - 1, - true + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } ); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); } #[test_only] fun initialize_with_integer(account: &signer) { - let (burn_cap, freeze_cap, mint_cap) = initialize( + let (burn_cap, freeze_cap, mint_cap) = + initialize( + account, + string::utf8(b"Fake money"), + string::utf8(b"FMD"), + 1, + true + ); + move_to( account, - string::utf8(b"Fake money"), - string::utf8(b"FMD"), - 1, - true + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } ); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); } - #[test(framework = @supra_framework, other = @0x123)] #[expected_failure(abort_code = 0x50003, location = supra_framework::system_addresses)] fun test_supply_initialize_fails(framework: signer, other: signer) { @@ -1835,7 +1991,9 @@ module supra_framework::coin { #[test(other = @0x123)] #[expected_failure(abort_code = 0x10003, location = Self)] - fun test_migration_coin_store_with_non_coin_type(other: signer) acquires CoinConversionMap, CoinStore, CoinInfo { + fun test_migration_coin_store_with_non_coin_type( + other: signer + ) acquires CoinConversionMap, CoinStore, CoinInfo { migrate_to_fungible_store_internal(&other); } @@ -1844,7 +2002,8 @@ module supra_framework::coin { aggregator_factory::initialize_aggregator_factory_for_test(&framework); initialize_with_aggregator(&framework); - let maybe_supply = &mut borrow_global_mut>(coin_address()).supply; + let maybe_supply = + &mut borrow_global_mut>(coin_address()).supply; let supply = option::borrow_mut(maybe_supply); // Supply should be parallelizable. @@ -1862,7 +2021,8 @@ module supra_framework::coin { aggregator_factory::initialize_aggregator_factory_for_test(&framework); initialize_with_aggregator(&framework); - let maybe_supply = &mut borrow_global_mut>(coin_address()).supply; + let maybe_supply = + &mut borrow_global_mut>(coin_address()).supply; let supply = option::borrow_mut(maybe_supply); optional_aggregator::add(supply, MAX_U128); @@ -1877,7 +2037,8 @@ module supra_framework::coin { aggregator_factory::initialize_aggregator_factory_for_test(&framework); initialize_with_integer(&framework); - let maybe_supply = &mut borrow_global_mut>(coin_address()).supply; + let maybe_supply = + &mut borrow_global_mut>(coin_address()).supply; let supply = option::borrow_mut(maybe_supply); // Supply should be non-parallelizable. @@ -1898,7 +2059,8 @@ module supra_framework::coin { initialize_with_integer(&framework); // Ensure we have a non-parellelizable non-zero supply. - let maybe_supply = &mut borrow_global_mut>(coin_address()).supply; + let maybe_supply = + &mut borrow_global_mut>(coin_address()).supply; let supply = option::borrow_mut(maybe_supply); assert!(!optional_aggregator::is_parallelizable(supply), 0); optional_aggregator::add(supply, 100); @@ -1908,31 +2070,37 @@ module supra_framework::coin { upgrade_supply(&framework); // Check supply again. - let maybe_supply = &mut borrow_global_mut>(coin_address()).supply; + let maybe_supply = + &mut borrow_global_mut>(coin_address()).supply; let supply = option::borrow_mut(maybe_supply); assert!(optional_aggregator::is_parallelizable(supply), 0); assert!(optional_aggregator::read(supply) == 100, 0); } #[test_only] - fun destroy_aggregatable_coin_for_test(aggregatable_coin: AggregatableCoin) { + fun destroy_aggregatable_coin_for_test( + aggregatable_coin: AggregatableCoin + ) { let AggregatableCoin { value } = aggregatable_coin; aggregator::destroy(value); } #[test(framework = @supra_framework)] public entry fun test_collect_from_and_drain( - framework: signer, + framework: signer ) acquires CoinInfo, CoinStore, CoinConversionMap, PairedCoinType { let framework_addr = signer::address_of(&framework); account::create_account_for_test(framework_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&framework, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(&framework, 1, true); // Collect from coin store only. let coins_minted = mint(100, &mint_cap); deposit(framework_addr, coins_minted); let aggregatable_coin = initialize_aggregatable_coin(&framework); - collect_into_aggregatable_coin(framework_addr, 50, &mut aggregatable_coin); + collect_into_aggregatable_coin( + framework_addr, 50, &mut aggregatable_coin + ); let fa_minted = coin_to_fungible_asset_internal(mint(100, &mint_cap)); primary_fungible_store::deposit(framework_addr, fa_minted); @@ -1940,12 +2108,16 @@ module supra_framework::coin { assert!(*option::borrow(&supply()) == 200, 0); // Collect from coin store and fungible store. - collect_into_aggregatable_coin(framework_addr, 100, &mut aggregatable_coin); + collect_into_aggregatable_coin( + framework_addr, 100, &mut aggregatable_coin + ); assert!(balance(framework_addr) == 50, 0); maybe_convert_to_fungible_store(framework_addr); // Collect from fungible store only. - collect_into_aggregatable_coin(framework_addr, 30, &mut aggregatable_coin); + collect_into_aggregatable_coin( + framework_addr, 30, &mut aggregatable_coin + ); // Check that aggregatable coin has the right amount. let collected_coin = drain_aggregatable_coin(&mut aggregatable_coin); @@ -1958,29 +2130,30 @@ module supra_framework::coin { burn(collected_coin, &burn_cap); destroy_aggregatable_coin_for_test(aggregatable_coin); - move_to(&framework, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + &framework, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test_only] - fun deposit_to_coin_store(account_addr: address, coin: Coin) acquires CoinStore { + fun deposit_to_coin_store( + account_addr: address, coin: Coin + ) acquires CoinStore { assert!( coin_store_exists(account_addr), - error::not_found(ECOIN_STORE_NOT_PUBLISHED), + error::not_found(ECOIN_STORE_NOT_PUBLISHED) ); let coin_store = borrow_global_mut>(account_addr); assert!( !coin_store.frozen, - error::permission_denied(EFROZEN), + error::permission_denied(EFROZEN) ); event::emit_event( &mut coin_store.deposit_events, - DepositEvent { amount: coin.value }, + DepositEvent { amount: coin.value } ); merge(&mut coin_store.coin, coin); @@ -1992,11 +2165,24 @@ module supra_framework::coin { ) acquires CoinConversionMap, CoinInfo, CoinStore, PairedCoinType, PairedFungibleAssetRefs { let account_addr = signer::address_of(account); account::create_account_for_test(account_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(account, 1, true); - assert!(fungible_asset::name(ensure_paired_metadata()) == name(), 0); - assert!(fungible_asset::symbol(ensure_paired_metadata()) == symbol(), 0); - assert!(fungible_asset::decimals(ensure_paired_metadata()) == decimals(), 0); + assert!( + fungible_asset::name(ensure_paired_metadata()) + == name(), + 0 + ); + assert!( + fungible_asset::symbol(ensure_paired_metadata()) + == symbol(), + 0 + ); + assert!( + fungible_asset::decimals(ensure_paired_metadata()) + == decimals(), + 0 + ); let minted_coin = mint(100, &mint_cap); let converted_fa = coin_to_fungible_asset_internal(minted_coin); @@ -2027,7 +2213,12 @@ module supra_framework::coin { maybe_convert_to_fungible_store(account_addr); assert!(!coin_store_exists(account_addr), 0); assert!(balance(account_addr) == 199, 0); - assert!(primary_fungible_store::balance(account_addr, ensure_paired_metadata()) == 199, 0); + assert!( + primary_fungible_store::balance( + account_addr, ensure_paired_metadata() + ) == 199, + 0 + ); let fa = coin_to_fungible_asset_internal(withdrawn_coin); fungible_asset::burn(&burn_ref, fa); @@ -2040,23 +2231,22 @@ module supra_framework::coin { assert!(paired_transfer_ref_exists(), 0); assert!(paired_burn_ref_exists(), 0); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @supra_framework, aaron = @0xcafe)] fun test_balance_with_both_stores( - account: &signer, - aaron: &signer + account: &signer, aaron: &signer ) acquires CoinConversionMap, CoinInfo, CoinStore { let account_addr = signer::address_of(account); let aaron_addr = signer::address_of(aaron); account::create_account_for_test(account_addr); account::create_account_for_test(aaron_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(account, 1, true); create_coin_store(aaron); let coin = mint(100, &mint_cap); let fa = coin_to_fungible_asset_internal(mint(100, &mint_cap)); @@ -2068,24 +2258,27 @@ module supra_framework::coin { assert!(balance(aaron_addr) == 200, 0); assert!(coin_balance(aaron_addr) == 0, 0); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @supra_framework)] - fun test_deposit( - account: &signer, - ) acquires CoinConversionMap, CoinInfo, CoinStore { + fun test_deposit(account: &signer) acquires CoinConversionMap, CoinInfo, CoinStore { let account_addr = signer::address_of(account); account::create_account_for_test(account_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(account, 1, true); let coin = mint(100, &mint_cap); deposit(account_addr, coin); assert!(coin_store_exists(account_addr), 0); - assert!(primary_fungible_store::balance(account_addr, ensure_paired_metadata()) == 0, 0); + assert!( + primary_fungible_store::balance( + account_addr, ensure_paired_metadata() + ) == 0, + 0 + ); assert!(balance(account_addr) == 100, 0); maybe_convert_to_fungible_store(account_addr); @@ -2093,22 +2286,27 @@ module supra_framework::coin { deposit(account_addr, coin); assert!(!coin_store_exists(account_addr), 0); assert!(balance(account_addr) == 200, 0); - assert!(primary_fungible_store::balance(account_addr, ensure_paired_metadata()) == 200, 0); + assert!( + primary_fungible_store::balance( + account_addr, ensure_paired_metadata() + ) == 200, + 0 + ); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @supra_framework)] fun test_withdraw( - account: &signer, + account: &signer ) acquires CoinConversionMap, CoinInfo, CoinStore, PairedCoinType { let account_addr = signer::address_of(account); account::create_account_for_test(account_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(account, 1, true); let coin = mint(200, &mint_cap); deposit_to_coin_store(account_addr, coin); assert!(coin_balance(account_addr) == 200, 0); @@ -2122,74 +2320,101 @@ module supra_framework::coin { let fa = coin_to_fungible_asset_internal(coin); primary_fungible_store::deposit(account_addr, fa); assert!(coin_store_exists(account_addr), 0); - assert!(primary_fungible_store::balance(account_addr, ensure_paired_metadata()) == 100, 0); + assert!( + primary_fungible_store::balance( + account_addr, ensure_paired_metadata() + ) == 100, + 0 + ); assert!(balance(account_addr) == 200, 0); // Withdraw from both coin store and fungible store. let coin = withdraw(account, 150); assert!(coin_balance(account_addr) == 0, 0); - assert!(primary_fungible_store::balance(account_addr, ensure_paired_metadata()) == 50, 0); + assert!( + primary_fungible_store::balance( + account_addr, ensure_paired_metadata() + ) == 50, + 0 + ); deposit_to_coin_store(account_addr, coin); maybe_convert_to_fungible_store(account_addr); assert!(!coin_store_exists(account_addr), 0); assert!(balance(account_addr) == 200, 0); - assert!(primary_fungible_store::balance(account_addr, ensure_paired_metadata()) == 200, 0); + assert!( + primary_fungible_store::balance( + account_addr, ensure_paired_metadata() + ) == 200, + 0 + ); // Withdraw from fungible store only. let coin = withdraw(account, 150); assert!(balance(account_addr) == 50, 0); burn(coin, &burn_cap); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @supra_framework)] fun test_supply( - account: &signer, + account: &signer ) acquires CoinConversionMap, CoinInfo, PairedCoinType, PairedFungibleAssetRefs { account::create_account_for_test(signer::address_of(account)); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(account, 1, true); let coin = mint(100, &mint_cap); ensure_paired_metadata(); let (mint_ref, mint_ref_receipt) = get_paired_mint_ref(&mint_cap); let (burn_ref, burn_ref_receipt) = get_paired_burn_ref(&burn_cap); let fungible_asset = fungible_asset::mint(&mint_ref, 50); - assert!(option::is_none(&fungible_asset::maximum(ensure_paired_metadata())), 0); + assert!( + option::is_none(&fungible_asset::maximum(ensure_paired_metadata())), + 0 + ); assert!(supply() == option::some(150), 0); assert!(coin_supply() == option::some(100), 0); - assert!(fungible_asset::supply(ensure_paired_metadata()) == option::some(50), 0); + assert!( + fungible_asset::supply(ensure_paired_metadata()) + == option::some(50), + 0 + ); let fa_from_coin = coin_to_fungible_asset_internal(coin); assert!(supply() == option::some(150), 0); assert!(coin_supply() == option::some(0), 0); - assert!(fungible_asset::supply(ensure_paired_metadata()) == option::some(150), 0); + assert!( + fungible_asset::supply(ensure_paired_metadata()) + == option::some(150), + 0 + ); let coin_from_fa = fungible_asset_to_coin(fungible_asset); assert!(supply() == option::some(150), 0); assert!(coin_supply() == option::some(50), 0); - assert!(fungible_asset::supply(ensure_paired_metadata()) == option::some(100), 0); + assert!( + fungible_asset::supply(ensure_paired_metadata()) + == option::some(100), + 0 + ); burn(coin_from_fa, &burn_cap); fungible_asset::burn(&burn_ref, fa_from_coin); assert!(supply() == option::some(0), 0); return_paired_mint_ref(mint_ref, mint_ref_receipt); return_paired_burn_ref(burn_ref, burn_ref_receipt); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @supra_framework, aaron = @0xaa10, bob = @0xb0b)] #[expected_failure(abort_code = 0x60005, location = Self)] fun test_force_deposit( - account: &signer, - aaron: &signer, - bob: &signer + account: &signer, aaron: &signer, bob: &signer ) acquires CoinConversionMap, CoinInfo, CoinStore { let account_addr = signer::address_of(account); let aaron_addr = signer::address_of(aaron); @@ -2197,30 +2422,32 @@ module supra_framework::coin { account::create_account_for_test(account_addr); account::create_account_for_test(aaron_addr); account::create_account_for_test(bob_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(account, 1, true); maybe_convert_to_fungible_store(aaron_addr); deposit(aaron_addr, mint(1, &mint_cap)); force_deposit(account_addr, mint(100, &mint_cap)); force_deposit(aaron_addr, mint(50, &mint_cap)); assert!( - primary_fungible_store::balance(aaron_addr, option::extract(&mut paired_metadata())) == 51, + primary_fungible_store::balance( + aaron_addr, option::extract(&mut paired_metadata()) + ) == 51, 0 ); assert!(coin_balance(account_addr) == 100, 0); force_deposit(bob_addr, mint(1, &mint_cap)); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @supra_framework, aaron = @0xaa10, bob = @0xb0b)] fun test_is_account_registered( account: &signer, aaron: &signer, - bob: &signer, + bob: &signer ) acquires CoinConversionMap, CoinInfo, CoinStore { let account_addr = signer::address_of(account); let aaron_addr = signer::address_of(aaron); @@ -2228,7 +2455,8 @@ module supra_framework::coin { account::create_account_for_test(account_addr); account::create_account_for_test(aaron_addr); account::create_account_for_test(bob_addr); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(account, 1, true); assert!(coin_store_exists(account_addr), 0); assert!(is_account_registered(account_addr), 0); @@ -2248,7 +2476,9 @@ module supra_framework::coin { assert!(is_account_registered(account_addr), 0); // Deposit FA to bob to created primary fungible store without `MigrationFlag`. - primary_fungible_store::deposit(bob_addr, coin_to_fungible_asset_internal(mint(100, &mint_cap))); + primary_fungible_store::deposit( + bob_addr, coin_to_fungible_asset_internal(mint(100, &mint_cap)) + ); assert!(!coin_store_exists(bob_addr), 0); register(bob); assert!(coin_store_exists(bob_addr), 0); @@ -2257,37 +2487,48 @@ module supra_framework::coin { register(bob); assert!(!coin_store_exists(bob_addr), 0); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } #[test(account = @supra_framework, aaron = @0xaa10)] fun test_migration_with_existing_primary_fungible_store( - account: &signer, + account: &signer ) acquires CoinConversionMap, CoinInfo, CoinStore, PairedCoinType { account::create_account_for_test(signer::address_of(account)); let account_addr = signer::address_of(account); - let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); + let (burn_cap, freeze_cap, mint_cap) = + initialize_and_register_fake_money(account, 1, true); let coin = mint(100, &mint_cap); - primary_fungible_store::deposit(account_addr, coin_to_fungible_asset_internal(coin)); + primary_fungible_store::deposit( + account_addr, coin_to_fungible_asset_internal(coin) + ); assert!(coin_balance(account_addr) == 0, 0); assert!(balance(account_addr) == 100, 0); let coin = withdraw(account, 50); - assert!(!migrated_primary_fungible_store_exists(account_addr, ensure_paired_metadata()), 0); + assert!( + !migrated_primary_fungible_store_exists( + account_addr, ensure_paired_metadata() + ), + 0 + ); maybe_convert_to_fungible_store(account_addr); - assert!(migrated_primary_fungible_store_exists(account_addr, ensure_paired_metadata()), 0); + assert!( + migrated_primary_fungible_store_exists( + account_addr, ensure_paired_metadata() + ), + 0 + ); deposit(account_addr, coin); assert!(coin_balance(account_addr) == 0, 0); assert!(balance(account_addr) == 100, 0); - move_to(account, FakeMoneyCapabilities { - burn_cap, - freeze_cap, - mint_cap, - }); + move_to( + account, + FakeMoneyCapabilities { burn_cap, freeze_cap, mint_cap } + ); } } diff --git a/aptos-move/framework/supra-framework/sources/coin.spec.move b/aptos-move/framework/supra-framework/sources/coin.spec.move index c3f007e496167..ca6727697b773 100644 --- a/aptos-move/framework/supra-framework/sources/coin.spec.move +++ b/aptos-move/framework/supra-framework/sources/coin.spec.move @@ -62,35 +62,53 @@ spec supra_framework::coin { pragma verify = true; global supply: num; global aggregate_supply: num; - apply TotalSupplyTracked to * except - initialize, initialize_internal, initialize_with_parallelizable_supply; + apply TotalSupplyTracked to * except initialize, initialize_internal, initialize_with_parallelizable_supply; // TODO(fa_migration) // apply TotalSupplyNoChange to * except mint, // burn, burn_from, initialize, initialize_internal, initialize_with_parallelizable_supply; } spec fun spec_fun_supply_tracked(val: u64, supply: Option): bool { - option::spec_is_some(supply) ==> val == optional_aggregator::optional_aggregator_value - (option::spec_borrow(supply)) + option::spec_is_some(supply) ==> + val + == optional_aggregator::optional_aggregator_value( + option::spec_borrow(supply) + ) } spec schema TotalSupplyTracked { - ensures old(spec_fun_supply_tracked(supply + aggregate_supply, - global>(type_info::type_of().account_address).supply)) ==> - spec_fun_supply_tracked(supply + aggregate_supply, - global>(type_info::type_of().account_address).supply); - } - - spec fun spec_fun_supply_no_change(old_supply: Option, - supply: Option): bool { - option::spec_is_some(old_supply) ==> optional_aggregator::optional_aggregator_value - (option::spec_borrow(old_supply)) == optional_aggregator::optional_aggregator_value - (option::spec_borrow(supply)) + ensures old( + spec_fun_supply_tracked( + supply + aggregate_supply, + global>(type_info::type_of().account_address) + .supply + ) + ) ==> + spec_fun_supply_tracked( + supply + aggregate_supply, + global>(type_info::type_of().account_address) + .supply + ); + } + + spec fun spec_fun_supply_no_change( + old_supply: Option, supply: Option + ): bool { + option::spec_is_some(old_supply) ==> + optional_aggregator::optional_aggregator_value( + option::spec_borrow(old_supply) + ) == optional_aggregator::optional_aggregator_value( + option::spec_borrow(supply) + ) } spec schema TotalSupplyNoChange { - let old_supply = global>(type_info::type_of().account_address).supply; - let post supply = global>(type_info::type_of().account_address).supply; + let old_supply = global>( + type_info::type_of().account_address + ).supply; + let post supply = global>( + type_info::type_of().account_address + ).supply; ensures spec_fun_supply_no_change(old_supply, supply); } @@ -162,7 +180,8 @@ spec supra_framework::coin { spec fun spec_paired_metadata(): Option> { if (exists(@supra_framework)) { - let map = global(@supra_framework).coin_to_fungible_asset_map; + let map = + global(@supra_framework).coin_to_fungible_asset_map; if (table::spec_contains(map, type_info::type_of())) { let metadata = table::spec_get(map, type_info::type_of()); option::spec_some(metadata) @@ -176,9 +195,13 @@ spec supra_framework::coin { spec fun spec_is_account_registered(account_addr: address): bool { let paired_metadata_opt = spec_paired_metadata(); - exists>(account_addr) || (option::spec_is_some( - paired_metadata_opt - ) && primary_fungible_store::spec_primary_store_exists(account_addr, option::spec_borrow(paired_metadata_opt))) + exists>(account_addr) + || ( + option::spec_is_some(paired_metadata_opt) + && primary_fungible_store::spec_primary_store_exists( + account_addr, option::spec_borrow(paired_metadata_opt) + ) + ) } spec schema CoinSubAbortsIf { @@ -186,9 +209,11 @@ spec supra_framework::coin { amount: u64; let addr = type_info::type_of().account_address; let maybe_supply = global>(addr).supply; - include (option::is_some( - maybe_supply - )) ==> optional_aggregator::SubAbortsIf { optional_aggregator: option::borrow(maybe_supply), value: amount }; + include (option::is_some(maybe_supply)) ==> + optional_aggregator::SubAbortsIf { + optional_aggregator: option::borrow(maybe_supply), + value: amount + }; } spec schema CoinAddAbortsIf { @@ -196,9 +221,11 @@ spec supra_framework::coin { amount: u64; let addr = type_info::type_of().account_address; let maybe_supply = global>(addr).supply; - include (option::is_some( - maybe_supply - )) ==> optional_aggregator::AddAbortsIf { optional_aggregator: option::borrow(maybe_supply), value: amount }; + include (option::is_some(maybe_supply)) ==> + optional_aggregator::AddAbortsIf { + optional_aggregator: option::borrow(maybe_supply), + value: amount + }; } spec schema AbortsIfNotExistCoinInfo { @@ -240,10 +267,7 @@ spec supra_framework::coin { }; } - spec burn( - coin: Coin, - _cap: &BurnCapability, - ) { + spec burn(coin: Coin, _cap: &BurnCapability) { // TODO(fa_migration) pragma verify = false; let addr = type_info::type_of().account_address; @@ -262,9 +286,7 @@ spec supra_framework::coin { } spec burn_from( - account_addr: address, - amount: u64, - burn_cap: &BurnCapability, + account_addr: address, amount: u64, burn_cap: &BurnCapability ) { // TODO(fa_migration) pragma verify = false; @@ -307,9 +329,8 @@ spec supra_framework::coin { modifies global>(account_addr); /// [high-level-req-8.3] include DepositAbortsIf; - ensures global>(account_addr).coin.value == old( - global>(account_addr) - ).coin.value + coin.value; + ensures global>(account_addr).coin.value + == old(global>(account_addr)).coin.value + coin.value; } spec coin_to_fungible_asset(coin: Coin): FungibleAsset { @@ -343,9 +364,8 @@ spec supra_framework::coin { pragma verify = false; modifies global>(account_addr); aborts_if !exists>(account_addr); - ensures global>(account_addr).coin.value == old( - global>(account_addr) - ).coin.value + coin.value; + ensures global>(account_addr).coin.value + == old(global>(account_addr)).coin.value + coin.value; } /// The value of `zero_coin` must be 0. @@ -365,8 +385,7 @@ spec supra_framework::coin { } spec freeze_coin_store( - account_addr: address, - _freeze_cap: &FreezeCapability, + account_addr: address, _freeze_cap: &FreezeCapability ) { // TODO(fa_migration) pragma verify = false; @@ -379,8 +398,7 @@ spec supra_framework::coin { } spec unfreeze_coin_store( - account_addr: address, - _freeze_cap: &FreezeCapability, + account_addr: address, _freeze_cap: &FreezeCapability ) { // TODO(fa_migration) pragma verify = false; @@ -414,10 +432,11 @@ spec supra_framework::coin { let post post_supply = option::spec_borrow(post_maybe_supply); let post post_value = optional_aggregator::optional_aggregator_value(post_supply); - let supply_no_parallel = option::spec_is_some(maybe_supply) && - !optional_aggregator::is_parallelizable(supply); + let supply_no_parallel = option::spec_is_some(maybe_supply) + && !optional_aggregator::is_parallelizable(supply); - aborts_if supply_no_parallel && !exists(@supra_framework); + aborts_if supply_no_parallel + && !exists(@supra_framework); ensures supply_no_parallel ==> optional_aggregator::is_parallelizable(post_supply) && post_value == value; } @@ -434,16 +453,17 @@ spec supra_framework::coin { // `account` must be `@supra_framework`. spec initialize_with_parallelizable_supply( - account: &signer, - name: string::String, - symbol: string::String, - decimals: u8, - monitor_supply: bool, + account: &signer, + name: string::String, + symbol: string::String, + decimals: u8, + monitor_supply: bool ): (BurnCapability, FreezeCapability, MintCapability) { use supra_framework::aggregator_factory; let addr = signer::address_of(account); aborts_if addr != @supra_framework; - aborts_if monitor_supply && !exists(@supra_framework); + aborts_if monitor_supply + && !exists(@supra_framework); include InitializeInternalSchema { name: name.bytes, symbol: symbol.bytes @@ -466,12 +486,12 @@ spec supra_framework::coin { } spec initialize_internal( - account: &signer, - name: string::String, - symbol: string::String, - decimals: u8, - monitor_supply: bool, - parallelizable: bool, + account: &signer, + name: string::String, + symbol: string::String, + decimals: u8, + monitor_supply: bool, + parallelizable: bool ): (BurnCapability, FreezeCapability, MintCapability) { include InitializeInternalSchema { name: name.bytes, @@ -483,15 +503,16 @@ spec supra_framework::coin { let post value = optional_aggregator::optional_aggregator_value(supply); let post limit = optional_aggregator::optional_aggregator_limit(supply); modifies global>(account_addr); - aborts_if monitor_supply && parallelizable + aborts_if monitor_supply + && parallelizable && !exists(@supra_framework); /// [managed_coin::high-level-req-2] ensures exists>(account_addr) && coin_info.name == name - && coin_info.symbol == symbol - && coin_info.decimals == decimals; + && coin_info.symbol == symbol && coin_info.decimals == decimals; ensures if (monitor_supply) { - value == 0 && limit == MAX_U128 + value == 0 + && limit == MAX_U128 && (parallelizable == optional_aggregator::is_parallelizable(supply)) } else { option::spec_is_none(coin_info.supply) @@ -523,11 +544,7 @@ spec supra_framework::coin { /// `from` and `to` account not frozen. /// `from` and `to` not the same address. /// `from` account sufficient balance. - spec transfer( - from: &signer, - to: address, - amount: u64, - ) { + spec transfer(from: &signer, to: address, amount: u64) { // TODO(fa_migration) pragma verify = false; let account_addr_from = signer::address_of(from); @@ -544,17 +561,16 @@ spec supra_framework::coin { aborts_if coin_store_to.frozen; aborts_if coin_store_from.coin.value < amount; - ensures account_addr_from != to ==> coin_store_post_from.coin.value == - coin_store_from.coin.value - amount; - ensures account_addr_from != to ==> coin_store_post_to.coin.value == coin_store_to.coin.value + amount; - ensures account_addr_from == to ==> coin_store_post_from.coin.value == coin_store_from.coin.value; + ensures account_addr_from != to ==> + coin_store_post_from.coin.value == coin_store_from.coin.value - amount; + ensures account_addr_from != to ==> + coin_store_post_to.coin.value == coin_store_to.coin.value + amount; + ensures account_addr_from == to ==> + coin_store_post_from.coin.value == coin_store_from.coin.value; } /// Account is not frozen and sufficient balance. - spec withdraw( - account: &signer, - amount: u64, - ): Coin { + spec withdraw(account: &signer, amount: u64): Coin { // TODO(fa_migration) pragma verify = false; include WithdrawAbortsIf; @@ -566,6 +582,7 @@ spec supra_framework::coin { ensures coin_post == balance - amount; ensures result == Coin { value: amount }; } + spec schema WithdrawAbortsIf { account: &signer; amount: u64; @@ -594,17 +611,21 @@ spec supra_framework::coin { ensures result.value == aggregator::spec_aggregator_get_val(old(coin).value); } - spec merge_aggregatable_coin(dst_coin: &mut AggregatableCoin, coin: Coin) { + spec merge_aggregatable_coin( + dst_coin: &mut AggregatableCoin, coin: Coin + ) { let aggr = dst_coin.value; let post p_aggr = dst_coin.value; - aborts_if aggregator::spec_aggregator_get_val(aggr) - + coin.value > aggregator::spec_get_limit(aggr); - aborts_if aggregator::spec_aggregator_get_val(aggr) - + coin.value > MAX_U128; - ensures aggregator::spec_aggregator_get_val(aggr) + coin.value == aggregator::spec_aggregator_get_val(p_aggr); + aborts_if aggregator::spec_aggregator_get_val(aggr) + coin.value + > aggregator::spec_get_limit(aggr); + aborts_if aggregator::spec_aggregator_get_val(aggr) + coin.value > MAX_U128; + ensures aggregator::spec_aggregator_get_val(aggr) + coin.value + == aggregator::spec_aggregator_get_val(p_aggr); } - spec collect_into_aggregatable_coin(account_addr: address, amount: u64, dst_coin: &mut AggregatableCoin) { + spec collect_into_aggregatable_coin( + account_addr: address, amount: u64, dst_coin: &mut AggregatableCoin + ) { // TODO(fa_migration) pragma verify = false; let aggr = dst_coin.value; @@ -613,11 +634,13 @@ spec supra_framework::coin { let post p_coin_store = global>(account_addr); aborts_if amount > 0 && !exists>(account_addr); aborts_if amount > 0 && coin_store.coin.value < amount; - aborts_if amount > 0 && aggregator::spec_aggregator_get_val(aggr) - + amount > aggregator::spec_get_limit(aggr); - aborts_if amount > 0 && aggregator::spec_aggregator_get_val(aggr) - + amount > MAX_U128; - ensures aggregator::spec_aggregator_get_val(aggr) + amount == aggregator::spec_aggregator_get_val(p_aggr); + aborts_if amount > 0 + && aggregator::spec_aggregator_get_val(aggr) + amount + > aggregator::spec_get_limit(aggr); + aborts_if amount > 0 + && aggregator::spec_aggregator_get_val(aggr) + amount > MAX_U128; + ensures aggregator::spec_aggregator_get_val(aggr) + amount + == aggregator::spec_aggregator_get_val(p_aggr); ensures coin_store.coin.value - amount == p_coin_store.coin.value; } } diff --git a/aptos-move/framework/supra-framework/sources/committee_map.move b/aptos-move/framework/supra-framework/sources/committee_map.move index b947263afa931..30b4a9425bed9 100644 --- a/aptos-move/framework/supra-framework/sources/committee_map.move +++ b/aptos-move/framework/supra-framework/sources/committee_map.move @@ -49,14 +49,14 @@ module supra_framework::committee_map { add_committee_member: EventHandle, remove_committee_member: EventHandle, update_node_info: EventHandle, - update_dkg_flag: EventHandle, + update_dkg_flag: EventHandle } struct CommitteeInfoStore has key { // map from unique committee id -> CommitteeInfo committee_map: SimpleMap, // map from node address to committee to which the node belongs - node_to_committee_map: SimpleMap, + node_to_committee_map: SimpleMap } struct CommitteeInfo has store, drop, copy { @@ -136,9 +136,15 @@ module supra_framework::committee_map { fun does_node_exist(committee: &CommitteeInfo, node_address: address): bool { simple_map::contains_key(&committee.map, &node_address) } + /// Internal - Assert if the node exists in the committee - fun ensure_node_address_exist(committee: &CommitteeInfo, node_address: address) { - assert!(does_node_exist(committee, node_address), error::invalid_argument(NODE_NOT_FOUND)) + fun ensure_node_address_exist( + committee: &CommitteeInfo, node_address: address + ) { + assert!( + does_node_exist(committee, node_address), + error::invalid_argument(NODE_NOT_FOUND) + ) } /// Internal - create OwnerCap @@ -148,30 +154,43 @@ module supra_framework::committee_map { /// Internal - create committeeInfo store functions fun create_committeeInfo_store(owner_signer: &signer): signer { - let (resource_signer, _) = account::create_resource_account(owner_signer, SEED_COMMITTEE); - move_to(&resource_signer, CommitteeInfoStore { - committee_map: simple_map::new(), - node_to_committee_map: simple_map::new() - }); + let (resource_signer, _) = + account::create_resource_account(owner_signer, SEED_COMMITTEE); + move_to( + &resource_signer, + CommitteeInfoStore { + committee_map: simple_map::new(), + node_to_committee_map: simple_map::new() + } + ); resource_signer } /// Internal - create event handler fun create_event_handler(resource_signer: &signer) { - move_to(resource_signer, SupraCommitteeEventHandler { - create: new_event_handle(resource_signer), - add_committee: new_event_handle(resource_signer), - remove_committee: new_event_handle(resource_signer), - update_committee: new_event_handle(resource_signer), - add_committee_member: new_event_handle(resource_signer), - remove_committee_member: new_event_handle(resource_signer), - update_node_info: new_event_handle(resource_signer), - update_dkg_flag: new_event_handle(resource_signer), - }); + move_to( + resource_signer, + SupraCommitteeEventHandler { + create: new_event_handle(resource_signer), + add_committee: new_event_handle(resource_signer), + remove_committee: new_event_handle(resource_signer), + update_committee: new_event_handle(resource_signer), + add_committee_member: new_event_handle( + resource_signer + ), + remove_committee_member: new_event_handle( + resource_signer + ), + update_node_info: new_event_handle(resource_signer), + update_dkg_flag: new_event_handle(resource_signer) + } + ); } fun get_committeeInfo_address(owner_signer: &signer): address { - account::create_resource_address(&signer::address_of(owner_signer), SEED_COMMITTEE) + account::create_resource_address( + &signer::address_of(owner_signer), SEED_COMMITTEE + ) } /// Its Initial function which will be executed automatically while deployed packages @@ -183,7 +202,9 @@ module supra_framework::committee_map { // Function to validate the committee type from an integer fun validate_committee_type(committee_type: u8, num_of_nodes: u64): u8 { - assert!(committee_type >= FAMILY && committee_type <= TRIBE, INVALID_COMMITTEE_TYPE); + assert!( + committee_type >= FAMILY && committee_type <= TRIBE, INVALID_COMMITTEE_TYPE + ); if (committee_type == FAMILY) { // f+1, number of nodes in a family committee should be greater than 1 assert!(num_of_nodes > 1, INVALID_NODE_NUMBERS); @@ -192,14 +213,18 @@ module supra_framework::committee_map { assert!(num_of_nodes >= 3 && num_of_nodes % 2 == 1, INVALID_NODE_NUMBERS); } else { // 3f+1, number of nodes in a tribe committee should be in the format of 3f+1 and greater than 4 - assert!(num_of_nodes >= 4 && (num_of_nodes - 1) % 3 == 0, INVALID_NODE_NUMBERS); + assert!( + num_of_nodes >= 4 && (num_of_nodes - 1) % 3 == 0, INVALID_NODE_NUMBERS + ); }; committee_type } #[view] /// Get the committee's node vector and committee type - public fun get_committee_info(com_store_addr: address, id: u64): (vector, u8) acquires CommitteeInfoStore { + public fun get_committee_info( + com_store_addr: address, id: u64 + ): (vector, u8) acquires CommitteeInfoStore { let committee_store = borrow_global(com_store_addr); let committee = simple_map::borrow(&committee_store.committee_map, &id); let (addrs, nodes) = simple_map::to_vec_pair(committee.map); @@ -214,7 +239,7 @@ module supra_framework::committee_map { network_public_key: node_info.network_public_key, cg_public_key: node_info.cg_public_key, network_port: node_info.network_port, - rpc_port: node_info.rpc_port, + rpc_port: node_info.rpc_port }; vector::push_back(&mut node_data_vec, node_data); }; @@ -231,8 +256,7 @@ module supra_framework::committee_map { #[view] /// Get the committee's id for a single node, only pass the address is okay public fun get_committee_id( - com_store_addr: address, - node_address: address + com_store_addr: address, node_address: address ): u64 acquires CommitteeInfoStore { let committee_store = borrow_global(com_store_addr); *simple_map::borrow(&committee_store.node_to_committee_map, &node_address) @@ -241,9 +265,7 @@ module supra_framework::committee_map { #[view] /// Get the node's information public fun get_node_info( - com_store_addr: address, - id: u64, - node_address: address + com_store_addr: address, id: u64, node_address: address ): NodeData acquires CommitteeInfoStore { let committee_store = borrow_global(com_store_addr); let committee = simple_map::borrow(&committee_store.committee_map, &id); @@ -259,38 +281,39 @@ module supra_framework::committee_map { network_public_key: node_info.network_public_key, cg_public_key: node_info.cg_public_key, network_port: node_info.network_port, - rpc_port: node_info.rpc_port, + rpc_port: node_info.rpc_port } } #[view] /// Get the committee's id for a single node public fun get_committee_id_for_node( - com_store_addr: address, - node_address: address + com_store_addr: address, node_address: address ): u64 acquires CommitteeInfoStore { let committee_store = borrow_global(com_store_addr); - let id = *simple_map::borrow(&committee_store.node_to_committee_map, &node_address); + let id = + *simple_map::borrow(&committee_store.node_to_committee_map, &node_address); id } #[view] /// Get a tuple of the node itself and node peers vector for a single node public fun get_peers_for_node( - com_store_addr: address, - node_address: address + com_store_addr: address, node_address: address ): (NodeData, vector) acquires CommitteeInfoStore { let committee_id = get_committee_id_for_node(com_store_addr, node_address); let this_node = get_node_info(com_store_addr, committee_id, node_address); - let (node_info,_) = get_committee_info(com_store_addr, committee_id); + let (node_info, _) = get_committee_info(com_store_addr, committee_id); let (_, index) = vector::index_of(&node_info, &this_node); - let self= vector::remove(&mut node_info, index); + let self = vector::remove(&mut node_info, index); (self, node_info) } #[view] /// Check if the committee has a valid dkg - public fun does_com_have_dkg(com_store_addr: address, com_id: u64): bool acquires CommitteeInfoStore { + public fun does_com_have_dkg( + com_store_addr: address, com_id: u64 + ): bool acquires CommitteeInfoStore { let committee_store = borrow_global(com_store_addr); let committee = simple_map::borrow(&committee_store.committee_map, &com_id); committee.has_valid_dkg @@ -306,15 +329,17 @@ module supra_framework::committee_map { // Only the OwnerCap capability can access it let _acquire = &capability::acquire(owner_signer, &OwnerCap {}); let committee_store = borrow_global_mut(com_store_addr); - let committee = simple_map::borrow_mut(&mut committee_store.committee_map, &com_id); + let committee = simple_map::borrow_mut( + &mut committee_store.committee_map, &com_id + ); committee.has_valid_dkg = flag_value; - let event_handler = borrow_global_mut(get_committeeInfo_address(owner_signer)); + let event_handler = + borrow_global_mut( + get_committeeInfo_address(owner_signer) + ); emit_event( &mut event_handler.update_dkg_flag, - UpdateDkgFlagEvent { - committee_id: com_id, - flag_value - } + UpdateDkgFlagEvent { committee_id: com_id, flag_value } ); } @@ -376,12 +401,14 @@ module supra_framework::committee_map { network_public_key: copy network_public_key, cg_public_key: copy cg_public_key, network_port, - rpc_port, + rpc_port }; vector::push_back(&mut node_infos, node_info); // Also update the node_to_committee_map let node_address = vector::pop_back(&mut node_addresses_for_iteration); - simple_map::upsert(&mut committee_store.node_to_committee_map, node_address, id); + simple_map::upsert( + &mut committee_store.node_to_committee_map, node_address, id + ); }; vector::reverse(&mut node_infos); let committee_info = CommitteeInfo { @@ -389,15 +416,17 @@ module supra_framework::committee_map { has_valid_dkg: false, committee_type: validate_committee_type(committee_type, node_address_len) }; - let event_handler = borrow_global_mut(get_committeeInfo_address(owner_signer)); - let (_, value) = simple_map::upsert(&mut committee_store.committee_map, id, committee_info); + let event_handler = + borrow_global_mut( + get_committeeInfo_address(owner_signer) + ); + let (_, value) = + simple_map::upsert(&mut committee_store.committee_map, id, committee_info); if (option::is_none(&value)) { emit_event( &mut event_handler.add_committee, - AddCommitteeEvent { - committee_id: id, - committee_info: copy committee_info - }, ) + AddCommitteeEvent { committee_id: id, committee_info: copy committee_info } + ) } else { emit_event( &mut event_handler.update_committee, @@ -405,7 +434,7 @@ module supra_framework::committee_map { committee_id: id, old_committee_info: option::destroy_some(value), new_committee_info: committee_info - }, + } ); // Destory the map simple_map::to_vec_pair(option::destroy_some(value).map); @@ -484,9 +513,7 @@ module supra_framework::committee_map { /// Remove the committee from the store public entry fun remove_committee( - owner_signer: &signer, - com_store_addr: address, - id: u64 + owner_signer: &signer, com_store_addr: address, id: u64 ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { // Only the OwnerCap capability can access it let _acquire = &capability::acquire(owner_signer, &OwnerCap {}); @@ -496,7 +523,8 @@ module supra_framework::committee_map { simple_map::contains_key(&committee_store.committee_map, &id), error::invalid_argument(INVALID_COMMITTEE_ID) ); - let (id, committee_info) = simple_map::remove(&mut committee_store.committee_map, &id); + let (id, committee_info) = + simple_map::remove(&mut committee_store.committee_map, &id); // Also remove the node_to_committee_map let (addrs, _) = simple_map::to_vec_pair(committee_info.map); while (vector::length(&addrs) > 0) { @@ -507,20 +535,19 @@ module supra_framework::committee_map { ); simple_map::remove(&mut committee_store.node_to_committee_map, &addr); }; - let event_handler = borrow_global_mut(get_committeeInfo_address(owner_signer)); + let event_handler = + borrow_global_mut( + get_committeeInfo_address(owner_signer) + ); emit_event( &mut event_handler.remove_committee, - RemoveCommitteeEvent { - committee_id: id, - committee_info: committee_info - }, ) + RemoveCommitteeEvent { committee_id: id, committee_info: committee_info } + ) } /// Remove the committee in bulk public entry fun remove_committee_bulk( - owner_signer: &signer, - com_store_addr: address, - ids: vector + owner_signer: &signer, com_store_addr: address, ids: vector ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { while (vector::length(&ids) > 0) { let id = vector::pop_back(&mut ids); @@ -539,7 +566,7 @@ module supra_framework::committee_map { network_public_key: vector, cg_public_key: vector, network_port: u16, - rpc_port: u16, + rpc_port: u16 ) acquires CommitteeInfoStore, SupraCommitteeEventHandler { // Only the OwnerCap capability can access it let _acquire = &capability::acquire(owner_signer, &OwnerCap {}); @@ -552,16 +579,17 @@ module supra_framework::committee_map { network_public_key: copy network_public_key, cg_public_key: copy cg_public_key, network_port: network_port, - rpc_port: rpc_port, + rpc_port: rpc_port }; - let event_handler = borrow_global_mut(get_committeeInfo_address(owner_signer)); + let event_handler = + borrow_global_mut( + get_committeeInfo_address(owner_signer) + ); if (!does_node_exist(committee, node_address)) { emit_event( &mut event_handler.add_committee_member, - AddCommitteeMemberEvent { - committee_id: id, - committee_member: node_info - }) + AddCommitteeMemberEvent { committee_id: id, committee_member: node_info } + ) } else { emit_event( &mut event_handler.update_node_info, @@ -569,7 +597,8 @@ module supra_framework::committee_map { committee_id: id, old_node_info: *simple_map::borrow(&committee.map, &node_address), new_node_info: node_info - }) + } + ) }; simple_map::upsert(&mut committee.map, node_address, node_info); // Also update the node_to_committee_map @@ -656,7 +685,10 @@ module supra_framework::committee_map { let committee = simple_map::borrow_mut(&mut committee_store.committee_map, &id); ensure_node_address_exist(committee, node_address); let (_, node_info) = simple_map::remove(&mut committee.map, &node_address); - let event_handler = borrow_global_mut(get_committeeInfo_address(owner_signer)); + let event_handler = + borrow_global_mut( + get_committeeInfo_address(owner_signer) + ); emit_event( &mut event_handler.remove_committee_member, RemoveCommitteeMemberEvent { @@ -667,7 +699,7 @@ module supra_framework::committee_map { network_public_key: node_info.network_public_key, cg_public_key: node_info.cg_public_key, network_port: node_info.network_port, - rpc_port: node_info.rpc_port, + rpc_port: node_info.rpc_port } } ); @@ -677,34 +709,38 @@ module supra_framework::committee_map { /// Find the node in the committee public fun find_node_in_committee( - com_store_add: address, - id: u64, - node_address: address + com_store_add: address, id: u64, node_address: address ): (bool, NodeData) acquires CommitteeInfoStore { let committee_store = borrow_global(com_store_add); let committee = simple_map::borrow(&committee_store.committee_map, &id); let flag = simple_map::contains_key(&committee.map, &node_address); if (!flag) { - return (false, NodeData { - operator: copy node_address, - ip_public_address: vector::empty(), - node_public_key: vector::empty(), - network_public_key: vector::empty(), - cg_public_key: vector::empty(), - network_port: 0, - rpc_port: 0, - }) + return ( + false, + NodeData { + operator: copy node_address, + ip_public_address: vector::empty(), + node_public_key: vector::empty(), + network_public_key: vector::empty(), + cg_public_key: vector::empty(), + network_port: 0, + rpc_port: 0 + } + ) } else { let node_info = *simple_map::borrow(&committee.map, &node_address); - (true, NodeData { - operator: copy node_address, - ip_public_address: node_info.ip_public_address, - node_public_key: node_info.node_public_key, - network_public_key: node_info.network_public_key, - cg_public_key: node_info.cg_public_key, - network_port: node_info.network_port, - rpc_port: node_info.rpc_port, - }) + ( + true, + NodeData { + operator: copy node_address, + ip_public_address: node_info.ip_public_address, + node_public_key: node_info.node_public_key, + network_public_key: node_info.network_public_key, + cg_public_key: node_info.cg_public_key, + network_port: node_info.network_port, + rpc_port: node_info.rpc_port + } + ) } } @@ -734,7 +770,7 @@ module supra_framework::committee_map { vector[123, 123], 1 ); - remove_committee(owner_signer,resource_address,1); + remove_committee(owner_signer, resource_address, 1); } #[test(owner_signer = @0xCEFEF)] @@ -821,7 +857,7 @@ module supra_framework::committee_map { vector[vector[vector[123], vector[124]], vector[vector[125], vector[126]]], vector[vector[123, 124], vector[125, 126]], vector[vector[123, 124], vector[125, 126]], - vector[1,1] + vector[1, 1] ); } @@ -968,7 +1004,7 @@ module supra_framework::committee_map { vector[123, 123], 1 ); - let (node_data,_) = get_committee_info(resource_address, 1); + let (node_data, _) = get_committee_info(resource_address, 1); assert!(vector::length(&node_data) == 2, 0); } @@ -1037,7 +1073,7 @@ module supra_framework::committee_map { vector[123, 123], 1 ); - let (_,peers) = get_peers_for_node(resource_address, @0x1); + let (_, peers) = get_peers_for_node(resource_address, @0x1); assert!(vector::length(&peers) == 1, 0); } } diff --git a/aptos-move/framework/supra-framework/sources/configs/config_buffer.move b/aptos-move/framework/supra-framework/sources/configs/config_buffer.move index dfd161e2a991b..a3704e9171dac 100644 --- a/aptos-move/framework/supra-framework/sources/configs/config_buffer.move +++ b/aptos-move/framework/supra-framework/sources/configs/config_buffer.move @@ -34,15 +34,13 @@ module supra_framework::config_buffer { const ESTD_SIGNER_NEEDED: u64 = 1; struct PendingConfigs has key { - configs: SimpleMap, + configs: SimpleMap } public fun initialize(supra_framework: &signer) { system_addresses::assert_supra_framework(supra_framework); if (!exists(@supra_framework)) { - move_to(supra_framework, PendingConfigs { - configs: simple_map::new(), - }) + move_to(supra_framework, PendingConfigs { configs: simple_map::new() }) } } @@ -51,9 +49,7 @@ module supra_framework::config_buffer { if (exists(@supra_framework)) { let config = borrow_global(@supra_framework); simple_map::contains_key(&config.configs, &type_info::type_name()) - } else { - false - } + } else { false } } /// Upsert an on-chain config to the buffer for the next epoch. @@ -79,7 +75,7 @@ module supra_framework::config_buffer { #[test_only] struct DummyConfig has drop, store { - data: u64, + data: u64 } #[test(fx = @std)] diff --git a/aptos-move/framework/supra-framework/sources/configs/config_buffer.spec.move b/aptos-move/framework/supra-framework/sources/configs/config_buffer.spec.move index e68efb0ee693a..9e09931b9ed65 100644 --- a/aptos-move/framework/supra-framework/sources/configs/config_buffer.spec.move +++ b/aptos-move/framework/supra-framework/sources/configs/config_buffer.spec.move @@ -13,9 +13,7 @@ spec supra_framework::config_buffer { if (exists(@supra_framework)) { let config = global(@supra_framework); simple_map::spec_contains_key(config.configs, type_name) - } else { - false - } + } else { false } } spec upsert(config: T) { @@ -31,9 +29,7 @@ spec supra_framework::config_buffer { let configs = global(@supra_framework); let key = type_info::type_name(); aborts_if !simple_map::spec_contains_key(configs.configs, key); - include any::UnpackAbortsIf { - x: simple_map::spec_get(configs.configs, key) - }; + include any::UnpackAbortsIf { x: simple_map::spec_get(configs.configs, key) }; } spec schema SetForNextEpochAbortsIf { @@ -50,9 +46,8 @@ spec supra_framework::config_buffer { let type_name = type_info::type_name(); let configs = global(@supra_framework); // TODO(#12015) - include spec_fun_does_exist(type_name) ==> any::UnpackAbortsIf { - x: simple_map::spec_get(configs.configs, type_name) - }; + include spec_fun_does_exist(type_name) ==> + any::UnpackAbortsIf { x: simple_map::spec_get(configs.configs, type_name) }; } spec schema OnNewEpochRequirement { @@ -60,9 +55,9 @@ spec supra_framework::config_buffer { let type_name = type_info::type_name(); let configs = global(@supra_framework); // TODO(#12015) - include spec_fun_does_exist(type_name) ==> any::UnpackRequirement { - x: simple_map::spec_get(configs.configs, type_name) - }; + include spec_fun_does_exist(type_name) ==> + any::UnpackRequirement { + x: simple_map::spec_get(configs.configs, type_name) + }; } - } diff --git a/aptos-move/framework/supra-framework/sources/configs/consensus_config.move b/aptos-move/framework/supra-framework/sources/configs/consensus_config.move index d402832c03cb6..f6b181eab9919 100644 --- a/aptos-move/framework/supra-framework/sources/configs/consensus_config.move +++ b/aptos-move/framework/supra-framework/sources/configs/consensus_config.move @@ -13,14 +13,16 @@ module supra_framework::consensus_config { friend supra_framework::reconfiguration_with_dkg; struct ConsensusConfig has drop, key, store { - config: vector, + config: vector } /// The provided on chain config bytes are empty or invalid const EINVALID_CONFIG: u64 = 1; /// Publishes the ConsensusConfig config. - public(friend) fun initialize(supra_framework: &signer, config: vector) { + public(friend) fun initialize( + supra_framework: &signer, config: vector + ) { system_addresses::assert_supra_framework(supra_framework); assert!(vector::length(&config) > 0, error::invalid_argument(EINVALID_CONFIG)); move_to(supra_framework, ConsensusConfig { config }); @@ -52,7 +54,7 @@ module supra_framework::consensus_config { public fun set_for_next_epoch(account: &signer, config: vector) { system_addresses::assert_supra_framework(account); assert!(vector::length(&config) > 0, error::invalid_argument(EINVALID_CONFIG)); - std::config_buffer::upsert(ConsensusConfig {config}); + std::config_buffer::upsert(ConsensusConfig { config }); } /// Only used in reconfigurations to apply the pending `ConsensusConfig`, if there is any. diff --git a/aptos-move/framework/supra-framework/sources/configs/consensus_config.spec.move b/aptos-move/framework/supra-framework/sources/configs/consensus_config.spec.move index 92b77ab44b094..26a5881aca01a 100644 --- a/aptos-move/framework/supra-framework/sources/configs/consensus_config.spec.move +++ b/aptos-move/framework/supra-framework/sources/configs/consensus_config.spec.move @@ -25,7 +25,8 @@ spec supra_framework::consensus_config { use supra_framework::chain_status; pragma verify = true; pragma aborts_if_is_strict; - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); } /// Ensure caller is admin. @@ -65,7 +66,8 @@ spec supra_framework::consensus_config { aborts_if !(len(config) > 0); requires chain_status::is_genesis(); - requires timestamp::spec_now_microseconds() >= reconfiguration::last_reconfiguration_time(); + requires timestamp::spec_now_microseconds() + >= reconfiguration::last_reconfiguration_time(); requires exists(@supra_framework); requires exists>(@supra_framework); ensures global(@supra_framework).config == config; @@ -84,7 +86,10 @@ spec supra_framework::consensus_config { spec validator_txn_enabled(): bool { pragma opaque; aborts_if !exists(@supra_framework); - ensures [abstract] result == spec_validator_txn_enabled_internal(global(@supra_framework).config); + ensures [abstract] result + == spec_validator_txn_enabled_internal( + global(@supra_framework).config + ); } spec validator_txn_enabled_internal(config_bytes: vector): bool { diff --git a/aptos-move/framework/supra-framework/sources/configs/execution_config.move b/aptos-move/framework/supra-framework/sources/configs/execution_config.move index ceb726ebefc57..55341129e3ef4 100644 --- a/aptos-move/framework/supra-framework/sources/configs/execution_config.move +++ b/aptos-move/framework/supra-framework/sources/configs/execution_config.move @@ -12,7 +12,7 @@ module supra_framework::execution_config { friend supra_framework::reconfiguration_with_dkg; struct ExecutionConfig has drop, key, store { - config: vector, + config: vector } /// The provided on chain config bytes are empty or invalid @@ -30,7 +30,8 @@ module supra_framework::execution_config { assert!(vector::length(&config) > 0, error::invalid_argument(EINVALID_CONFIG)); if (exists(@supra_framework)) { - let config_ref = &mut borrow_global_mut(@supra_framework).config; + let config_ref = + &mut borrow_global_mut(@supra_framework).config; *config_ref = config; } else { move_to(account, ExecutionConfig { config }); diff --git a/aptos-move/framework/supra-framework/sources/configs/execution_config.spec.move b/aptos-move/framework/supra-framework/sources/configs/execution_config.spec.move index 811fca0716142..f3252a58a3afa 100644 --- a/aptos-move/framework/supra-framework/sources/configs/execution_config.spec.move +++ b/aptos-move/framework/supra-framework/sources/configs/execution_config.spec.move @@ -24,10 +24,12 @@ spec supra_framework::execution_config { requires exists(@supra_framework); requires exists(@supra_framework); requires len(config) > 0; - include features::spec_periodical_reward_rate_decrease_enabled() ==> staking_config::StakingRewardsConfigEnabledRequirement; + include features::spec_periodical_reward_rate_decrease_enabled() ==> + staking_config::StakingRewardsConfigEnabledRequirement; include supra_coin::ExistsSupraCoin; requires system_addresses::is_supra_framework_address(addr); - requires timestamp::spec_now_microseconds() >= reconfiguration::last_reconfiguration_time(); + requires timestamp::spec_now_microseconds() + >= reconfiguration::last_reconfiguration_time(); ensures exists(@supra_framework); } diff --git a/aptos-move/framework/supra-framework/sources/configs/gas_schedule.move b/aptos-move/framework/supra-framework/sources/configs/gas_schedule.move index ca9aab630b9e5..f9d2d3b569866 100644 --- a/aptos-move/framework/supra-framework/sources/configs/gas_schedule.move +++ b/aptos-move/framework/supra-framework/sources/configs/gas_schedule.move @@ -27,7 +27,7 @@ module supra_framework::gas_schedule { struct GasEntry has store, copy, drop { key: String, - val: u64, + val: u64 } struct GasSchedule has key, copy, drop { @@ -36,13 +36,18 @@ module supra_framework::gas_schedule { struct GasScheduleV2 has key, copy, drop, store { feature_version: u64, - entries: vector, + entries: vector } /// Only called during genesis. - public(friend) fun initialize(supra_framework: &signer, gas_schedule_blob: vector) { + public(friend) fun initialize( + supra_framework: &signer, gas_schedule_blob: vector + ) { system_addresses::assert_supra_framework(supra_framework); - assert!(!vector::is_empty(&gas_schedule_blob), error::invalid_argument(EINVALID_GAS_SCHEDULE)); + assert!( + !vector::is_empty(&gas_schedule_blob), + error::invalid_argument(EINVALID_GAS_SCHEDULE) + ); // TODO(Gas): check if gas schedule is consistent let gas_schedule: GasScheduleV2 = from_bytes(gas_schedule_blob); @@ -54,20 +59,26 @@ module supra_framework::gas_schedule { /// WARNING: calling this while randomness is enabled will trigger a new epoch without randomness! /// /// TODO: update all the tests that reference this function, then disable this function. - public fun set_gas_schedule(supra_framework: &signer, gas_schedule_blob: vector) acquires GasSchedule, GasScheduleV2 { + public fun set_gas_schedule( + supra_framework: &signer, gas_schedule_blob: vector + ) acquires GasSchedule, GasScheduleV2 { system_addresses::assert_supra_framework(supra_framework); - assert!(!vector::is_empty(&gas_schedule_blob), error::invalid_argument(EINVALID_GAS_SCHEDULE)); + assert!( + !vector::is_empty(&gas_schedule_blob), + error::invalid_argument(EINVALID_GAS_SCHEDULE) + ); chain_status::assert_genesis(); if (exists(@supra_framework)) { let gas_schedule = borrow_global_mut(@supra_framework); let new_gas_schedule: GasScheduleV2 = from_bytes(gas_schedule_blob); - assert!(new_gas_schedule.feature_version >= gas_schedule.feature_version, - error::invalid_argument(EINVALID_GAS_FEATURE_VERSION)); + assert!( + new_gas_schedule.feature_version >= gas_schedule.feature_version, + error::invalid_argument(EINVALID_GAS_FEATURE_VERSION) + ); // TODO(Gas): check if gas schedule is consistent *gas_schedule = new_gas_schedule; - } - else { + } else { if (exists(@supra_framework)) { _ = move_from(@supra_framework); }; @@ -88,9 +99,14 @@ module supra_framework::gas_schedule { /// supra_framework::gas_schedule::set_for_next_epoch(&framework_signer, some_gas_schedule_blob); /// supra_framework::supra_governance::reconfigure(&framework_signer); /// ``` - public fun set_for_next_epoch(supra_framework: &signer, gas_schedule_blob: vector) acquires GasScheduleV2 { + public fun set_for_next_epoch( + supra_framework: &signer, gas_schedule_blob: vector + ) acquires GasScheduleV2 { system_addresses::assert_supra_framework(supra_framework); - assert!(!vector::is_empty(&gas_schedule_blob), error::invalid_argument(EINVALID_GAS_SCHEDULE)); + assert!( + !vector::is_empty(&gas_schedule_blob), + error::invalid_argument(EINVALID_GAS_SCHEDULE) + ); let new_gas_schedule: GasScheduleV2 = from_bytes(gas_schedule_blob); if (exists(@supra_framework)) { let cur_gas_schedule = borrow_global(@supra_framework); @@ -111,7 +127,10 @@ module supra_framework::gas_schedule { new_gas_schedule_blob: vector ) acquires GasScheduleV2 { system_addresses::assert_supra_framework(supra_framework); - assert!(!vector::is_empty(&new_gas_schedule_blob), error::invalid_argument(EINVALID_GAS_SCHEDULE)); + assert!( + !vector::is_empty(&new_gas_schedule_blob), + error::invalid_argument(EINVALID_GAS_SCHEDULE) + ); let new_gas_schedule: GasScheduleV2 = from_bytes(new_gas_schedule_blob); if (exists(@supra_framework)) { @@ -144,32 +163,32 @@ module supra_framework::gas_schedule { } } - public fun set_storage_gas_config(supra_framework: &signer, config: StorageGasConfig) { + public fun set_storage_gas_config( + supra_framework: &signer, config: StorageGasConfig + ) { storage_gas::set_config(supra_framework, config); // Need to trigger reconfiguration so the VM is guaranteed to load the new gas fee starting from the next // transaction. reconfiguration::reconfigure(); } - public fun set_storage_gas_config_for_next_epoch(supra_framework: &signer, config: StorageGasConfig) { + public fun set_storage_gas_config_for_next_epoch( + supra_framework: &signer, config: StorageGasConfig + ) { storage_gas::set_config(supra_framework, config); } #[test(fx = @0x1)] - #[expected_failure(abort_code=0x010002, location = Self)] - fun set_for_next_epoch_should_abort_if_gas_version_is_too_old(fx: signer) acquires GasScheduleV2 { + #[expected_failure(abort_code = 0x010002, location = Self)] + fun set_for_next_epoch_should_abort_if_gas_version_is_too_old( + fx: signer + ) acquires GasScheduleV2 { // Setup. - let old_gas_schedule = GasScheduleV2 { - feature_version: 1000, - entries: vector[], - }; + let old_gas_schedule = GasScheduleV2 { feature_version: 1000, entries: vector[] }; move_to(&fx, old_gas_schedule); // Setting an older version should not work. - let new_gas_schedule = GasScheduleV2 { - feature_version: 999, - entries: vector[], - }; + let new_gas_schedule = GasScheduleV2 { feature_version: 999, entries: vector[] }; let new_bytes = to_bytes(&new_gas_schedule); set_for_next_epoch(&fx, new_bytes); } diff --git a/aptos-move/framework/supra-framework/sources/configs/gas_schedule.spec.move b/aptos-move/framework/supra-framework/sources/configs/gas_schedule.spec.move index ef7adb907defe..f5ac3f0c21fce 100644 --- a/aptos-move/framework/supra-framework/sources/configs/gas_schedule.spec.move +++ b/aptos-move/framework/supra-framework/sources/configs/gas_schedule.spec.move @@ -39,7 +39,7 @@ spec supra_framework::gas_schedule { let addr = signer::address_of(supra_framework); /// [high-level-req-1] - include system_addresses::AbortsIfNotAptosFramework{ account: supra_framework }; + include system_addresses::AbortsIfNotAptosFramework { account: supra_framework }; /// [high-level-req-3.3] aborts_if len(gas_schedule_blob) == 0; aborts_if exists(addr); @@ -65,13 +65,14 @@ spec supra_framework::gas_schedule { include staking_config::StakingRewardsConfigRequirement; /// [high-level-req-2] - include system_addresses::AbortsIfNotAptosFramework{ account: supra_framework }; + include system_addresses::AbortsIfNotAptosFramework { account: supra_framework }; /// [high-level-req-3.2] aborts_if len(gas_schedule_blob) == 0; let new_gas_schedule = util::spec_from_bytes(gas_schedule_blob); let gas_schedule = global(@supra_framework); /// [high-level-req-4] - aborts_if exists(@supra_framework) && new_gas_schedule.feature_version < gas_schedule.feature_version; + aborts_if exists(@supra_framework) + && new_gas_schedule.feature_version < gas_schedule.feature_version; ensures exists(signer::address_of(supra_framework)); ensures global(@supra_framework) == new_gas_schedule; } @@ -87,7 +88,7 @@ spec supra_framework::gas_schedule { pragma verify_duration_estimate = 600; requires exists(@supra_framework); requires exists>(@supra_framework); - include system_addresses::AbortsIfNotAptosFramework{ account: supra_framework }; + include system_addresses::AbortsIfNotAptosFramework { account: supra_framework }; include transaction_fee::RequiresCollectedFeesPerValueLeqBlockAptosSupply; include staking_config::StakingRewardsConfigRequirement; aborts_if !exists(@supra_framework); @@ -97,31 +98,43 @@ spec supra_framework::gas_schedule { spec set_for_next_epoch(supra_framework: &signer, gas_schedule_blob: vector) { use supra_framework::util; - include system_addresses::AbortsIfNotAptosFramework{ account: supra_framework }; + include system_addresses::AbortsIfNotAptosFramework { account: supra_framework }; include config_buffer::SetForNextEpochAbortsIf { account: supra_framework, config: gas_schedule_blob }; let new_gas_schedule = util::spec_from_bytes(gas_schedule_blob); let cur_gas_schedule = global(@supra_framework); - aborts_if exists(@supra_framework) && new_gas_schedule.feature_version < cur_gas_schedule.feature_version; + aborts_if exists(@supra_framework) + && new_gas_schedule.feature_version < cur_gas_schedule.feature_version; } - spec set_for_next_epoch_check_hash(supra_framework: &signer, old_gas_schedule_hash: vector, new_gas_schedule_blob: vector) { + spec set_for_next_epoch_check_hash( + supra_framework: &signer, + old_gas_schedule_hash: vector, + new_gas_schedule_blob: vector + ) { use aptos_std::aptos_hash; use std::bcs; use std::features; use supra_framework::util; - include system_addresses::AbortsIfNotAptosFramework{ account: supra_framework }; + include system_addresses::AbortsIfNotAptosFramework { account: supra_framework }; include config_buffer::SetForNextEpochAbortsIf { account: supra_framework, config: new_gas_schedule_blob }; let new_gas_schedule = util::spec_from_bytes(new_gas_schedule_blob); let cur_gas_schedule = global(@supra_framework); - aborts_if exists(@supra_framework) && new_gas_schedule.feature_version < cur_gas_schedule.feature_version; - aborts_if exists(@supra_framework) && (!features::spec_sha_512_and_ripemd_160_enabled() || aptos_hash::spec_sha3_512_internal(bcs::serialize(cur_gas_schedule)) != old_gas_schedule_hash); + aborts_if exists(@supra_framework) + && new_gas_schedule.feature_version < cur_gas_schedule.feature_version; + aborts_if exists(@supra_framework) + && ( + !features::spec_sha_512_and_ripemd_160_enabled() + || aptos_hash::spec_sha3_512_internal( + bcs::serialize(cur_gas_schedule) + ) != old_gas_schedule_hash + ); } spec on_new_epoch(framework: &signer) { @@ -131,12 +144,14 @@ spec supra_framework::gas_schedule { } spec set_storage_gas_config(supra_framework: &signer, config: storage_gas::StorageGasConfig) { - include system_addresses::AbortsIfNotAptosFramework{ account: supra_framework }; + include system_addresses::AbortsIfNotAptosFramework { account: supra_framework }; aborts_if !exists(@supra_framework); } - spec set_storage_gas_config_for_next_epoch(supra_framework: &signer, config: storage_gas::StorageGasConfig) { - include system_addresses::AbortsIfNotAptosFramework{ account: supra_framework }; + spec set_storage_gas_config_for_next_epoch( + supra_framework: &signer, config: storage_gas::StorageGasConfig + ) { + include system_addresses::AbortsIfNotAptosFramework { account: supra_framework }; aborts_if !exists(@supra_framework); } } diff --git a/aptos-move/framework/supra-framework/sources/configs/jwk_consensus_config.move b/aptos-move/framework/supra-framework/sources/configs/jwk_consensus_config.move index a7d8fa7114a37..d130c13f6464e 100644 --- a/aptos-move/framework/supra-framework/sources/configs/jwk_consensus_config.move +++ b/aptos-move/framework/supra-framework/sources/configs/jwk_consensus_config.move @@ -25,7 +25,7 @@ module supra_framework::jwk_consensus_config { /// Currently the variant type is one of the following. /// - `ConfigOff` /// - `ConfigV1` - variant: Any, + variant: Any } /// A JWK consensus config variant indicating JWK consensus should not run. @@ -33,12 +33,12 @@ module supra_framework::jwk_consensus_config { struct OIDCProvider has copy, drop, store { name: String, - config_url: String, + config_url: String } /// A JWK consensus config variant indicating JWK consensus should run to watch a given list of OIDC providers. struct ConfigV1 has copy, drop, store { - oidc_providers: vector, + oidc_providers: vector } /// Initialize the configuration. Used in genesis or governance. @@ -59,7 +59,9 @@ module supra_framework::jwk_consensus_config { /// jwk_consensus_config::set_for_next_epoch(&framework_signer, config); /// supra_governance::reconfigure(&framework_signer); /// ``` - public fun set_for_next_epoch(framework: &signer, config: JWKConsensusConfig) { + public fun set_for_next_epoch( + framework: &signer, config: JWKConsensusConfig + ) { system_addresses::assert_supra_framework(framework); config_buffer::upsert(config); } @@ -80,7 +82,7 @@ module supra_framework::jwk_consensus_config { /// Construct a `JWKConsensusConfig` of variant `ConfigOff`. public fun new_off(): JWKConsensusConfig { JWKConsensusConfig { - variant: copyable_any::pack( ConfigOff {} ) + variant: copyable_any::pack(ConfigOff {}) } } @@ -89,15 +91,18 @@ module supra_framework::jwk_consensus_config { /// Abort if the given provider list contains duplicated provider names. public fun new_v1(oidc_providers: vector): JWKConsensusConfig { let name_set = simple_map::new(); - vector::for_each_ref(&oidc_providers, |provider| { - let provider: &OIDCProvider = provider; - let (_, old_value) = simple_map::upsert(&mut name_set, provider.name, 0); - if (option::is_some(&old_value)) { - abort(error::invalid_argument(EDUPLICATE_PROVIDERS)) + vector::for_each_ref( + &oidc_providers, + |provider| { + let provider: &OIDCProvider = provider; + let (_, old_value) = simple_map::upsert(&mut name_set, provider.name, 0); + if (option::is_some(&old_value)) { + abort(error::invalid_argument(EDUPLICATE_PROVIDERS)) + } } - }); + ); JWKConsensusConfig { - variant: copyable_any::pack( ConfigV1 { oidc_providers } ) + variant: copyable_any::pack(ConfigV1 { oidc_providers }) } } @@ -108,7 +113,7 @@ module supra_framework::jwk_consensus_config { #[test_only] fun enabled(): bool acquires JWKConsensusConfig { - let variant= borrow_global(@supra_framework).variant; + let variant = borrow_global(@supra_framework).variant; let variant_type_name = *string::bytes(copyable_any::type_name(&variant)); variant_type_name != b"0x1::jwk_consensus_config::ConfigOff" } @@ -122,10 +127,13 @@ module supra_framework::jwk_consensus_config { #[test(framework = @0x1)] fun init_buffer_apply(framework: signer) acquires JWKConsensusConfig { initialize_for_testing(&framework); - let config = new_v1(vector[ - new_oidc_provider(utf8(b"Bob"), utf8(b"https://bob.dev")), - new_oidc_provider(utf8(b"Alice"), utf8(b"https://alice.io")), - ]); + let config = + new_v1( + vector[ + new_oidc_provider(utf8(b"Bob"), utf8(b"https://bob.dev")), + new_oidc_provider(utf8(b"Alice"), utf8(b"https://alice.io")) + ] + ); set_for_next_epoch(&framework, config); on_new_epoch(&framework); assert!(enabled(), 1); @@ -138,11 +146,13 @@ module supra_framework::jwk_consensus_config { #[test] #[expected_failure(abort_code = 0x010001, location = Self)] fun name_uniqueness_in_config_v1() { - new_v1(vector[ - new_oidc_provider(utf8(b"Alice"), utf8(b"https://alice.info")), - new_oidc_provider(utf8(b"Bob"), utf8(b"https://bob.dev")), - new_oidc_provider(utf8(b"Alice"), utf8(b"https://alice.io")), - ]); + new_v1( + vector[ + new_oidc_provider(utf8(b"Alice"), utf8(b"https://alice.info")), + new_oidc_provider(utf8(b"Bob"), utf8(b"https://bob.dev")), + new_oidc_provider(utf8(b"Alice"), utf8(b"https://alice.io")) + ] + ); } } diff --git a/aptos-move/framework/supra-framework/sources/configs/randomness_api_v0_config.move b/aptos-move/framework/supra-framework/sources/configs/randomness_api_v0_config.move index 7040ea4002262..83df9ad86ee1c 100644 --- a/aptos-move/framework/supra-framework/sources/configs/randomness_api_v0_config.move +++ b/aptos-move/framework/supra-framework/sources/configs/randomness_api_v0_config.move @@ -6,16 +6,20 @@ module supra_framework::randomness_api_v0_config { friend supra_framework::reconfiguration_with_dkg; struct RequiredGasDeposit has key, drop, store { - gas_amount: Option, + gas_amount: Option } /// If this flag is set, `max_gas` specified inside `#[randomness()]` will be used as the required deposit. struct AllowCustomMaxGasFlag has key, drop, store { - value: bool, + value: bool } /// Only used in genesis. - fun initialize(framework: &signer, required_amount: RequiredGasDeposit, allow_custom_max_gas_flag: AllowCustomMaxGasFlag) { + fun initialize( + framework: &signer, + required_amount: RequiredGasDeposit, + allow_custom_max_gas_flag: AllowCustomMaxGasFlag + ) { system_addresses::assert_supra_framework(framework); chain_status::assert_genesis(); move_to(framework, required_amount); @@ -23,15 +27,19 @@ module supra_framework::randomness_api_v0_config { } /// This can be called by on-chain governance to update `RequiredGasDeposit` for the next epoch. - public fun set_for_next_epoch(framework: &signer, gas_amount: Option) { + public fun set_for_next_epoch( + framework: &signer, gas_amount: Option + ) { system_addresses::assert_supra_framework(framework); config_buffer::upsert(RequiredGasDeposit { gas_amount }); } /// This can be called by on-chain governance to update `AllowCustomMaxGasFlag` for the next epoch. - public fun set_allow_max_gas_flag_for_next_epoch(framework: &signer, value: bool) { + public fun set_allow_max_gas_flag_for_next_epoch( + framework: &signer, value: bool + ) { system_addresses::assert_supra_framework(framework); - config_buffer::upsert(AllowCustomMaxGasFlag { value } ); + config_buffer::upsert(AllowCustomMaxGasFlag { value }); } /// Only used in reconfigurations to apply the pending `RequiredGasDeposit`, if there is any. diff --git a/aptos-move/framework/supra-framework/sources/configs/randomness_config.move b/aptos-move/framework/supra-framework/sources/configs/randomness_config.move index 98e2e79ca2973..630c36e14234c 100644 --- a/aptos-move/framework/supra-framework/sources/configs/randomness_config.move +++ b/aptos-move/framework/supra-framework/sources/configs/randomness_config.move @@ -17,7 +17,7 @@ module supra_framework::randomness_config { /// Currently the variant type is one of the following. /// - `ConfigOff` /// - `ConfigV1` - variant: Any, + variant: Any } /// A randomness config variant indicating the feature is disabled. @@ -28,7 +28,7 @@ module supra_framework::randomness_config { /// Any validator subset should not be able to reconstruct randomness if `subset_power / total_power <= secrecy_threshold`, secrecy_threshold: FixedPoint64, /// Any validator subset should be able to reconstruct randomness if `subset_power / total_power > reconstruction_threshold`. - reconstruction_threshold: FixedPoint64, + reconstruction_threshold: FixedPoint64 } /// A randomness config variant indicating the feature is enabled with fast path. @@ -38,7 +38,7 @@ module supra_framework::randomness_config { /// Any validator subset should be able to reconstruct randomness if `subset_power / total_power > reconstruction_threshold`. reconstruction_threshold: FixedPoint64, /// Any validator subset should not be able to reconstruct randomness via the fast path if `subset_power / total_power <= fast_path_secrecy_threshold`, - fast_path_secrecy_threshold: FixedPoint64, + fast_path_secrecy_threshold: FixedPoint64 } /// Initialize the configuration. Used in genesis or governance. @@ -50,7 +50,9 @@ module supra_framework::randomness_config { } /// This can be called by on-chain governance to update on-chain consensus configs for the next epoch. - public fun set_for_next_epoch(framework: &signer, new_config: RandomnessConfig) { + public fun set_for_next_epoch( + framework: &signer, new_config: RandomnessConfig + ) { system_addresses::assert_supra_framework(framework); config_buffer::upsert(new_config); } @@ -75,27 +77,27 @@ module supra_framework::randomness_config { public fun enabled(): bool acquires RandomnessConfig { if (exists(@supra_framework)) { let config = borrow_global(@supra_framework); - let variant_type_name = *string::bytes(copyable_any::type_name(&config.variant)); + let variant_type_name = + *string::bytes(copyable_any::type_name(&config.variant)); variant_type_name != b"0x1::randomness_config::ConfigOff" - } else { - false - } + } else { false } } /// Create a `ConfigOff` variant. public fun new_off(): RandomnessConfig { RandomnessConfig { - variant: copyable_any::pack( ConfigOff {} ) + variant: copyable_any::pack(ConfigOff {}) } } /// Create a `ConfigV1` variant. - public fun new_v1(secrecy_threshold: FixedPoint64, reconstruction_threshold: FixedPoint64): RandomnessConfig { + public fun new_v1( + secrecy_threshold: FixedPoint64, reconstruction_threshold: FixedPoint64 + ): RandomnessConfig { RandomnessConfig { - variant: copyable_any::pack( ConfigV1 { - secrecy_threshold, - reconstruction_threshold - } ) + variant: copyable_any::pack( + ConfigV1 { secrecy_threshold, reconstruction_threshold } + ) } } @@ -103,14 +105,16 @@ module supra_framework::randomness_config { public fun new_v2( secrecy_threshold: FixedPoint64, reconstruction_threshold: FixedPoint64, - fast_path_secrecy_threshold: FixedPoint64, + fast_path_secrecy_threshold: FixedPoint64 ): RandomnessConfig { RandomnessConfig { - variant: copyable_any::pack( ConfigV2 { - secrecy_threshold, - reconstruction_threshold, - fast_path_secrecy_threshold, - } ) + variant: copyable_any::pack( + ConfigV2 { + secrecy_threshold, + reconstruction_threshold, + fast_path_secrecy_threshold + } + ) } } @@ -137,10 +141,11 @@ module supra_framework::randomness_config { initialize_for_testing(&framework); // Enabling. - let config = new_v1( - fixed_point64::create_from_rational(1, 2), - fixed_point64::create_from_rational(2, 3) - ); + let config = + new_v1( + fixed_point64::create_from_rational(1, 2), + fixed_point64::create_from_rational(2, 3) + ); set_for_next_epoch(&framework, config); on_new_epoch(&framework); assert!(enabled(), 1); diff --git a/aptos-move/framework/supra-framework/sources/configs/randomness_config_seqnum.move b/aptos-move/framework/supra-framework/sources/configs/randomness_config_seqnum.move index d4179cb6bfbbf..cf98a33431a96 100644 --- a/aptos-move/framework/supra-framework/sources/configs/randomness_config_seqnum.move +++ b/aptos-move/framework/supra-framework/sources/configs/randomness_config_seqnum.move @@ -16,7 +16,7 @@ module supra_framework::randomness_config_seqnum { /// If this seqnum is smaller than a validator local override, the on-chain `RandomnessConfig` will be ignored. /// Useful in a chain recovery from randomness stall. struct RandomnessConfigSeqNum has drop, key, store { - seq_num: u64, + seq_num: u64 } /// Update `RandomnessConfigSeqNum`. diff --git a/aptos-move/framework/supra-framework/sources/configs/staking_config.move b/aptos-move/framework/supra-framework/sources/configs/staking_config.move index f79079402d05d..77cc0acd60a44 100644 --- a/aptos-move/framework/supra-framework/sources/configs/staking_config.move +++ b/aptos-move/framework/supra-framework/sources/configs/staking_config.move @@ -291,9 +291,7 @@ module supra_framework::staking_config { /// Update the min and max stake amounts. /// Can only be called as part of the Supra governance proposal process established by the SupraGovernance module. public fun update_required_stake( - supra_framework: &signer, - minimum_stake: u64, - maximum_stake: u64 + supra_framework: &signer, minimum_stake: u64, maximum_stake: u64 ) acquires StakingConfig { system_addresses::assert_supra_framework(supra_framework); validate_required_stake(minimum_stake, maximum_stake); @@ -322,9 +320,7 @@ module supra_framework::staking_config { /// Update the rewards rate. /// Can only be called as part of the Supra governance proposal process established by the AptosGovernance module. public fun update_rewards_rate( - supra_framework: &signer, - new_rewards_rate: u64, - new_rewards_rate_denominator: u64 + supra_framework: &signer, new_rewards_rate: u64, new_rewards_rate_denominator: u64 ) acquires StakingConfig { assert!( !features::periodical_reward_rate_decrease_enabled(), @@ -798,7 +794,9 @@ module supra_framework::staking_config { vector[] ); timestamp::set_time_has_started_for_testing(supra_framework); - timestamp::update_global_time_for_test_secs(last_rewards_rate_period_start_in_secs); + timestamp::update_global_time_for_test_secs( + last_rewards_rate_period_start_in_secs + ); initialize_rewards( supra_framework, rewards_rate, diff --git a/aptos-move/framework/supra-framework/sources/configs/staking_config.spec.move b/aptos-move/framework/supra-framework/sources/configs/staking_config.spec.move index 227b9d8007499..cb48f81d6c3ad 100644 --- a/aptos-move/framework/supra-framework/sources/configs/staking_config.spec.move +++ b/aptos-move/framework/supra-framework/sources/configs/staking_config.spec.move @@ -57,7 +57,8 @@ spec supra_framework::staking_config { /// spec module { use supra_framework::chain_status; - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); pragma verify = true; pragma aborts_if_is_strict; } @@ -80,8 +81,8 @@ spec supra_framework::staking_config { spec StakingRewardsConfig { invariant fixed_point64::spec_less_or_equal( - rewards_rate, - fixed_point64::spec_create_from_u128((1u128))); + rewards_rate, fixed_point64::spec_create_from_u128((1u128)) + ); invariant fixed_point64::spec_less_or_equal(min_rewards_rate, rewards_rate); invariant rewards_rate_period_in_secs > 0; invariant fixed_point64::spec_ceil(rewards_rate_decrease_rate) <= 1; @@ -102,7 +103,7 @@ spec supra_framework::staking_config { allow_validator_set_change: bool, rewards_rate: u64, rewards_rate_denominator: u64, - voting_power_increase_limit: u64, + voting_power_increase_limit: u64 ) { use std::signer; let addr = signer::address_of(supra_framework); @@ -130,7 +131,7 @@ spec supra_framework::staking_config { min_rewards_rate: FixedPoint64, rewards_rate_period_in_secs: u64, last_rewards_rate_period_start_in_secs: u64, - rewards_rate_decrease_rate: FixedPoint64, + rewards_rate_decrease_rate: FixedPoint64 ) { use std::signer; pragma verify_duration_estimate = 120; @@ -138,7 +139,8 @@ spec supra_framework::staking_config { let addr = signer::address_of(supra_framework); /// [high-level-req-1.2] aborts_if addr != @supra_framework; - aborts_if last_rewards_rate_period_start_in_secs > timestamp::spec_now_seconds(); + aborts_if last_rewards_rate_period_start_in_secs + > timestamp::spec_now_seconds(); include StakingRewardsConfigValidationAbortsIf; aborts_if exists(addr); ensures exists(addr); @@ -150,18 +152,28 @@ spec supra_framework::staking_config { spec get_reward_rate(config: &StakingConfig): (u64, u64) { include StakingRewardsConfigRequirement; - ensures (features::spec_periodical_reward_rate_decrease_enabled() && - (global(@supra_framework).rewards_rate.value as u64) != 0) ==> - result_1 <= MAX_REWARDS_RATE && result_2 <= MAX_U64; + ensures ( + features::spec_periodical_reward_rate_decrease_enabled() + && ( + global(@supra_framework).rewards_rate.value as u64 + ) != 0 + ) ==> + result_1 <= MAX_REWARDS_RATE + && result_2 <= MAX_U64; } spec reward_rate(): (u64, u64) { let config = global(@supra_framework); aborts_if !exists(@supra_framework); include StakingRewardsConfigRequirement; - ensures (features::spec_periodical_reward_rate_decrease_enabled() && - (global(@supra_framework).rewards_rate.value as u64) != 0) ==> - result_1 <= MAX_REWARDS_RATE && result_2 <= MAX_U64; + ensures ( + features::spec_periodical_reward_rate_decrease_enabled() + && ( + global(@supra_framework).rewards_rate.value as u64 + ) != 0 + ) ==> + result_1 <= MAX_REWARDS_RATE + && result_2 <= MAX_U64; } spec calculate_and_save_latest_epoch_rewards_rate(): FixedPoint64 { @@ -182,9 +194,7 @@ spec supra_framework::staking_config { /// The maximum_stake must be greater than maximum_stake in the range of Specified stake and the maximum_stake greater than zero. /// The StakingConfig is under @supra_framework. spec update_required_stake( - supra_framework: &signer, - minimum_stake: u64, - maximum_stake: u64, + supra_framework: &signer, minimum_stake: u64, maximum_stake: u64 ) { use std::signer; let addr = signer::address_of(supra_framework); @@ -192,16 +202,15 @@ spec supra_framework::staking_config { aborts_if addr != @supra_framework; aborts_if minimum_stake > maximum_stake || maximum_stake == 0; aborts_if !exists(@supra_framework); - ensures global(@supra_framework).minimum_stake == minimum_stake && - global(@supra_framework).maximum_stake == maximum_stake; + ensures global(@supra_framework).minimum_stake == minimum_stake + && global(@supra_framework).maximum_stake == maximum_stake; } /// Caller must be @supra_framework. /// The new_recurring_lockup_duration_secs must greater than zero. /// The StakingConfig is under @supra_framework. spec update_recurring_lockup_duration_secs( - supra_framework: &signer, - new_recurring_lockup_duration_secs: u64, + supra_framework: &signer, new_recurring_lockup_duration_secs: u64 ) { use std::signer; let addr = signer::address_of(supra_framework); @@ -210,7 +219,8 @@ spec supra_framework::staking_config { /// [high-level-req-3.2] aborts_if new_recurring_lockup_duration_secs == 0; aborts_if !exists(@supra_framework); - ensures global(@supra_framework).recurring_lockup_duration_secs == new_recurring_lockup_duration_secs; + ensures global(@supra_framework).recurring_lockup_duration_secs + == new_recurring_lockup_duration_secs; } /// Caller must be @supra_framework. @@ -219,9 +229,7 @@ spec supra_framework::staking_config { /// The `rewards_rate` which is the numerator is limited to be `<= MAX_REWARDS_RATE` in order to avoid the arithmetic overflow in the rewards calculation. /// rewards_rate/rewards_rate_denominator <= 1. spec update_rewards_rate( - supra_framework: &signer, - new_rewards_rate: u64, - new_rewards_rate_denominator: u64, + supra_framework: &signer, new_rewards_rate: u64, new_rewards_rate_denominator: u64 ) { use std::signer; aborts_if features::spec_periodical_reward_rate_decrease_enabled(); @@ -244,7 +252,7 @@ spec supra_framework::staking_config { rewards_rate: FixedPoint64, min_rewards_rate: FixedPoint64, rewards_rate_period_in_secs: u64, - rewards_rate_decrease_rate: FixedPoint64, + rewards_rate_decrease_rate: FixedPoint64 ) { use std::signer; pragma verify_duration_estimate = 120; // verified but takes long @@ -252,31 +260,35 @@ spec supra_framework::staking_config { let addr = signer::address_of(supra_framework); /// [high-level-req-1.6] aborts_if addr != @supra_framework; - aborts_if global(@supra_framework).rewards_rate_period_in_secs != rewards_rate_period_in_secs; + aborts_if global(@supra_framework).rewards_rate_period_in_secs + != rewards_rate_period_in_secs; include StakingRewardsConfigValidationAbortsIf; aborts_if !exists(addr); let post staking_rewards_config = global(@supra_framework); ensures staking_rewards_config.rewards_rate == rewards_rate; ensures staking_rewards_config.min_rewards_rate == min_rewards_rate; - ensures staking_rewards_config.rewards_rate_period_in_secs == rewards_rate_period_in_secs; - ensures staking_rewards_config.rewards_rate_decrease_rate == rewards_rate_decrease_rate; + ensures staking_rewards_config.rewards_rate_period_in_secs + == rewards_rate_period_in_secs; + ensures staking_rewards_config.rewards_rate_decrease_rate + == rewards_rate_decrease_rate; } /// Caller must be @supra_framework. /// Only this %0-%50 of current total voting power is allowed to join the validator set in each epoch. /// The StakingConfig is under @supra_framework. spec update_voting_power_increase_limit( - supra_framework: &signer, - new_voting_power_increase_limit: u64, + supra_framework: &signer, new_voting_power_increase_limit: u64 ) { use std::signer; let addr = signer::address_of(supra_framework); /// [high-level-req-1.7] aborts_if addr != @supra_framework; /// [high-level-req-2.2] - aborts_if new_voting_power_increase_limit == 0 || new_voting_power_increase_limit > 50; + aborts_if new_voting_power_increase_limit == 0 + || new_voting_power_increase_limit > 50; aborts_if !exists(@supra_framework); - ensures global(@supra_framework).voting_power_increase_limit == new_voting_power_increase_limit; + ensures global(@supra_framework).voting_power_increase_limit + == new_voting_power_increase_limit; } /// The maximum_stake must be greater than maximum_stake in the range of Specified stake and the maximum_stake greater than zero. @@ -289,7 +301,7 @@ spec supra_framework::staking_config { rewards_rate: FixedPoint64, min_rewards_rate: FixedPoint64, rewards_rate_period_in_secs: u64, - rewards_rate_decrease_rate: FixedPoint64, + rewards_rate_decrease_rate: FixedPoint64 ) { include StakingRewardsConfigValidationAbortsIf; } @@ -305,8 +317,8 @@ spec supra_framework::staking_config { rewards_rate_decrease_rate: FixedPoint64; aborts_if fixed_point64::spec_greater( - rewards_rate, - fixed_point64::spec_create_from_u128((1u128))); + rewards_rate, fixed_point64::spec_create_from_u128((1u128)) + ); aborts_if fixed_point64::spec_greater(min_rewards_rate, rewards_rate); aborts_if rewards_rate_period_in_secs == 0; aborts_if fixed_point64::spec_ceil(rewards_rate_decrease_rate) > 1; @@ -314,7 +326,8 @@ spec supra_framework::staking_config { spec schema StakingRewardsConfigRequirement { requires exists(@supra_framework); - include features::spec_periodical_reward_rate_decrease_enabled() ==> StakingRewardsConfigEnabledRequirement; + include features::spec_periodical_reward_rate_decrease_enabled() ==> + StakingRewardsConfigEnabledRequirement; } spec schema StakingRewardsConfigEnabledRequirement { @@ -327,12 +340,13 @@ spec supra_framework::staking_config { let rewards_rate_decrease_rate = staking_rewards_config.rewards_rate_decrease_rate; requires fixed_point64::spec_less_or_equal( - rewards_rate, - fixed_point64::spec_create_from_u128((1u128))); + rewards_rate, fixed_point64::spec_create_from_u128((1u128)) + ); requires fixed_point64::spec_less_or_equal(min_rewards_rate, rewards_rate); requires rewards_rate_period_in_secs > 0; /// [high-level-req-4] - requires last_rewards_rate_period_start_in_secs <= timestamp::spec_now_seconds(); + requires last_rewards_rate_period_start_in_secs + <= timestamp::spec_now_seconds(); requires fixed_point64::spec_ceil(rewards_rate_decrease_rate) <= 1; } } diff --git a/aptos-move/framework/supra-framework/sources/configs/supra_config.move b/aptos-move/framework/supra-framework/sources/configs/supra_config.move index d2785ef01827f..f27099b1703a9 100644 --- a/aptos-move/framework/supra-framework/sources/configs/supra_config.move +++ b/aptos-move/framework/supra-framework/sources/configs/supra_config.move @@ -10,14 +10,16 @@ module supra_framework::supra_config { friend supra_framework::reconfiguration_with_dkg; struct SupraConfig has drop, key, store { - config: vector, + config: vector } /// The provided on chain config bytes are empty or invalid const EINVALID_CONFIG: u64 = 1; /// Publishes the SupraConfig config. - public(friend) fun initialize(supra_framework: &signer, config: vector) { + public(friend) fun initialize( + supra_framework: &signer, config: vector + ) { system_addresses::assert_supra_framework(supra_framework); assert!(vector::length(&config) > 0, error::invalid_argument(EINVALID_CONFIG)); move_to(supra_framework, SupraConfig { config }); @@ -32,7 +34,7 @@ module supra_framework::supra_config { public fun set_for_next_epoch(account: &signer, config: vector) { system_addresses::assert_supra_framework(account); assert!(vector::length(&config) > 0, error::invalid_argument(EINVALID_CONFIG)); - std::config_buffer::upsert(SupraConfig {config}); + std::config_buffer::upsert(SupraConfig { config }); } /// Only used in reconfigurations to apply the pending `SupraConfig`, if there is any. diff --git a/aptos-move/framework/supra-framework/sources/configs/supra_config.spec.move b/aptos-move/framework/supra-framework/sources/configs/supra_config.spec.move index ccbdcc75b996f..04f3929544bf8 100644 --- a/aptos-move/framework/supra-framework/sources/configs/supra_config.spec.move +++ b/aptos-move/framework/supra-framework/sources/configs/supra_config.spec.move @@ -19,7 +19,8 @@ spec supra_framework::supra_config { use supra_framework::chain_status; pragma verify = true; pragma aborts_if_is_strict; - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); } /// Ensure caller is admin. diff --git a/aptos-move/framework/supra-framework/sources/configs/version.move b/aptos-move/framework/supra-framework/sources/configs/version.move index 45fe8ebb714a5..02ff43eca5390 100644 --- a/aptos-move/framework/supra-framework/sources/configs/version.move +++ b/aptos-move/framework/supra-framework/sources/configs/version.move @@ -12,7 +12,7 @@ module supra_framework::version { friend supra_framework::reconfiguration_with_dkg; struct Version has drop, key, store { - major: u64, + major: u64 } struct SetVersionCapability has key {} @@ -24,7 +24,9 @@ module supra_framework::version { /// Only called during genesis. /// Publishes the Version config. - public(friend) fun initialize(supra_framework: &signer, initial_version: u64) { + public(friend) fun initialize( + supra_framework: &signer, initial_version: u64 + ) { system_addresses::assert_supra_framework(supra_framework); move_to(supra_framework, Version { major: initial_version }); @@ -39,7 +41,10 @@ module supra_framework::version { /// /// TODO: update all the tests that reference this function, then disable this function. public entry fun set_version(account: &signer, major: u64) acquires Version { - assert!(exists(signer::address_of(account)), error::permission_denied(ENOT_AUTHORIZED)); + assert!( + exists(signer::address_of(account)), + error::permission_denied(ENOT_AUTHORIZED) + ); chain_status::assert_genesis(); let old_major = borrow_global(@supra_framework).major; @@ -57,10 +62,13 @@ module supra_framework::version { /// - `supra_framework::version::set_for_next_epoch(&framework_signer, new_version);` /// - `supra_framework::supra_governance::reconfigure(&framework_signer);` public entry fun set_for_next_epoch(account: &signer, major: u64) acquires Version { - assert!(exists(signer::address_of(account)), error::permission_denied(ENOT_AUTHORIZED)); + assert!( + exists(signer::address_of(account)), + error::permission_denied(ENOT_AUTHORIZED) + ); let old_major = borrow_global(@supra_framework).major; assert!(old_major < major, error::invalid_argument(EINVALID_MAJOR_VERSION_NUMBER)); - config_buffer::upsert(Version {major}); + config_buffer::upsert(Version { major }); } /// Only used in reconfigurations to apply the pending `Version`, if there is any. @@ -93,8 +101,7 @@ module supra_framework::version { #[test(supra_framework = @supra_framework, core_resources = @core_resources)] public entry fun test_set_version_core_resources( - supra_framework: signer, - core_resources: signer, + supra_framework: signer, core_resources: signer ) acquires Version { initialize(&supra_framework, 1); assert!(borrow_global(@supra_framework).major == 1, 0); @@ -106,8 +113,7 @@ module supra_framework::version { #[test(supra_framework = @supra_framework, random_account = @0x123)] #[expected_failure(abort_code = 327682, location = Self)] public entry fun test_set_version_unauthorized_should_fail( - supra_framework: signer, - random_account: signer, + supra_framework: signer, random_account: signer ) acquires Version { initialize(&supra_framework, 1); set_version(&random_account, 2); diff --git a/aptos-move/framework/supra-framework/sources/configs/version.spec.move b/aptos-move/framework/supra-framework/sources/configs/version.spec.move index 69345174ca667..629ac7557f57c 100644 --- a/aptos-move/framework/supra-framework/sources/configs/version.spec.move +++ b/aptos-move/framework/supra-framework/sources/configs/version.spec.move @@ -38,7 +38,8 @@ spec supra_framework::version { include transaction_fee::RequiresCollectedFeesPerValueLeqBlockAptosSupply; include staking_config::StakingRewardsConfigRequirement; requires chain_status::is_genesis(); - requires timestamp::spec_now_microseconds() >= reconfiguration::last_reconfiguration_time(); + requires timestamp::spec_now_microseconds() + >= reconfiguration::last_reconfiguration_time(); requires exists(@supra_framework); requires exists>(@supra_framework); @@ -63,7 +64,8 @@ spec supra_framework::version { ensures exists(@supra_framework); ensures exists(@supra_framework); ensures global(@supra_framework) == Version { major: initial_version }; - ensures global(@supra_framework) == SetVersionCapability {}; + ensures global(@supra_framework) + == SetVersionCapability {}; } spec set_for_next_epoch(account: &signer, major: u64) { diff --git a/aptos-move/framework/supra-framework/sources/dispatchable_fungible_asset.move b/aptos-move/framework/supra-framework/sources/dispatchable_fungible_asset.move index e86426a3c3e21..6ef05d1a0baf5 100644 --- a/aptos-move/framework/supra-framework/sources/dispatchable_fungible_asset.move +++ b/aptos-move/framework/supra-framework/sources/dispatchable_fungible_asset.move @@ -41,19 +41,19 @@ module supra_framework::dispatchable_fungible_asset { constructor_ref: &ConstructorRef, withdraw_function: Option, deposit_function: Option, - derived_balance_function: Option, + derived_balance_function: Option ) { fungible_asset::register_dispatch_functions( constructor_ref, withdraw_function, deposit_function, - derived_balance_function, + derived_balance_function ); let store_obj = &object::generate_signer(constructor_ref); move_to( store_obj, TransferRefStore { - transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref), + transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref) } ); } @@ -64,7 +64,7 @@ module supra_framework::dispatchable_fungible_asset { public fun withdraw( owner: &signer, store: Object, - amount: u64, + amount: u64 ): FungibleAsset acquires TransferRefStore { fungible_asset::withdraw_sanity_check(owner, store, false); let func_opt = fungible_asset::withdraw_dispatch_function(store); @@ -80,10 +80,12 @@ module supra_framework::dispatchable_fungible_asset { store, amount, borrow_transfer_ref(store), - func, + func ); let end_balance = fungible_asset::balance(store); - assert!(amount <= start_balance - end_balance, error::aborted(EAMOUNT_MISMATCH)); + assert!( + amount <= start_balance - end_balance, error::aborted(EAMOUNT_MISMATCH) + ); fa } else { fungible_asset::withdraw_internal(object::object_address(&store), amount) @@ -120,7 +122,7 @@ module supra_framework::dispatchable_fungible_asset { sender: &signer, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires TransferRefStore { let fa = withdraw(sender, from, amount); deposit(to, fa); @@ -162,10 +164,11 @@ module supra_framework::dispatchable_fungible_asset { } } - inline fun borrow_transfer_ref(metadata: Object): &TransferRef acquires TransferRefStore { - let metadata_addr = object::object_address( - &fungible_asset::store_metadata(metadata) - ); + inline fun borrow_transfer_ref( + metadata: Object + ): &TransferRef acquires TransferRefStore { + let metadata_addr = + object::object_address(&fungible_asset::store_metadata(metadata)); assert!( exists(metadata_addr), error::not_found(ESTORE_NOT_FOUND) @@ -177,18 +180,17 @@ module supra_framework::dispatchable_fungible_asset { store: Object, amount: u64, transfer_ref: &TransferRef, - function: &FunctionInfo, + function: &FunctionInfo ): FungibleAsset; native fun dispatchable_deposit( store: Object, fa: FungibleAsset, transfer_ref: &TransferRef, - function: &FunctionInfo, + function: &FunctionInfo ); native fun dispatchable_derived_balance( - store: Object, - function: &FunctionInfo, + store: Object, function: &FunctionInfo ): u64; } diff --git a/aptos-move/framework/supra-framework/sources/dispatchable_fungible_asset.spec.move b/aptos-move/framework/supra-framework/sources/dispatchable_fungible_asset.spec.move index b5df8d7fafca6..ffbfa618d5702 100644 --- a/aptos-move/framework/supra-framework/sources/dispatchable_fungible_asset.spec.move +++ b/aptos-move/framework/supra-framework/sources/dispatchable_fungible_asset.spec.move @@ -11,7 +11,7 @@ spec supra_framework::dispatchable_fungible_asset { pragma opaque; } - spec dispatchable_derived_balance{ + spec dispatchable_derived_balance { pragma opaque; } } diff --git a/aptos-move/framework/supra-framework/sources/dkg.move b/aptos-move/framework/supra-framework/sources/dkg.move index 9721c2722bd6f..fbe64126ec671 100644 --- a/aptos-move/framework/supra-framework/sources/dkg.move +++ b/aptos-move/framework/supra-framework/sources/dkg.move @@ -19,13 +19,13 @@ module supra_framework::dkg { dealer_epoch: u64, randomness_config: RandomnessConfig, dealer_validator_set: vector, - target_validator_set: vector, + target_validator_set: vector } #[event] struct DKGStartEvent has drop, store { session_metadata: DKGSessionMetadata, - start_time_us: u64, + start_time_us: u64 } /// The input and output of a DKG session. @@ -33,13 +33,13 @@ module supra_framework::dkg { struct DKGSessionState has copy, store, drop { metadata: DKGSessionMetadata, start_time_us: u64, - transcript: vector, + transcript: vector } /// The completed and in-progress DKG sessions. struct DKGState has key { last_completed: Option, - in_progress: Option, + in_progress: Option } /// Called in genesis to initialize on-chain states. @@ -50,7 +50,7 @@ module supra_framework::dkg { supra_framework, DKGState { last_completed: std::option::none(), - in_progress: std::option::none(), + in_progress: std::option::none() } ); } @@ -62,26 +62,27 @@ module supra_framework::dkg { dealer_epoch: u64, randomness_config: RandomnessConfig, dealer_validator_set: vector, - target_validator_set: vector, + target_validator_set: vector ) acquires DKGState { let dkg_state = borrow_global_mut(@supra_framework); let new_session_metadata = DKGSessionMetadata { dealer_epoch, randomness_config, dealer_validator_set, - target_validator_set, + target_validator_set }; let start_time_us = timestamp::now_microseconds(); - dkg_state.in_progress = std::option::some(DKGSessionState { - metadata: new_session_metadata, - start_time_us, - transcript: vector[], - }); + dkg_state.in_progress = std::option::some( + DKGSessionState { + metadata: new_session_metadata, + start_time_us, + transcript: vector[] + } + ); - emit(DKGStartEvent { - start_time_us, - session_metadata: new_session_metadata, - }); + emit( + DKGStartEvent { start_time_us, session_metadata: new_session_metadata } + ); } /// Put a transcript into the currently incomplete DKG session, then mark it completed. @@ -89,7 +90,10 @@ module supra_framework::dkg { /// Abort if DKG is not in progress. public(friend) fun finish(transcript: vector) acquires DKGState { let dkg_state = borrow_global_mut(@supra_framework); - assert!(option::is_some(&dkg_state.in_progress), error::invalid_state(EDKG_NOT_IN_PROGRESS)); + assert!( + option::is_some(&dkg_state.in_progress), + error::invalid_state(EDKG_NOT_IN_PROGRESS) + ); let session = option::extract(&mut dkg_state.in_progress); session.transcript = transcript; dkg_state.last_completed = option::some(session); diff --git a/aptos-move/framework/supra-framework/sources/dkg.spec.move b/aptos-move/framework/supra-framework/sources/dkg.spec.move index dcedf6065fdfb..d5a5ea905893f 100644 --- a/aptos-move/framework/supra-framework/sources/dkg.spec.move +++ b/aptos-move/framework/supra-framework/sources/dkg.spec.move @@ -2,7 +2,8 @@ spec supra_framework::dkg { spec module { use supra_framework::chain_status; - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); } spec initialize(supra_framework: &signer) { @@ -15,7 +16,7 @@ spec supra_framework::dkg { dealer_epoch: u64, randomness_config: RandomnessConfig, dealer_validator_set: vector, - target_validator_set: vector, + target_validator_set: vector ) { aborts_if !exists(@supra_framework); aborts_if !exists(@supra_framework); @@ -31,9 +32,7 @@ spec supra_framework::dkg { spec fun has_incomplete_session(): bool { if (exists(@supra_framework)) { option::spec_is_some(global(@supra_framework).in_progress) - } else { - false - } + } else { false } } spec try_clear_incomplete_session(fx: &signer) { diff --git a/aptos-move/framework/supra-framework/sources/event.move b/aptos-move/framework/supra-framework/sources/event.move index 3ce57788f9be1..cde43f34edc15 100644 --- a/aptos-move/framework/supra-framework/sources/event.move +++ b/aptos-move/framework/supra-framework/sources/event.move @@ -35,21 +35,20 @@ module supra_framework::event { /// Total number of events emitted to this event stream. counter: u64, /// A globally unique ID for this event stream. - guid: GUID, + guid: GUID } #[deprecated] /// Use EventHandleGenerator to generate a unique event handle for `sig` public(friend) fun new_event_handle(guid: GUID): EventHandle { - EventHandle { - counter: 0, - guid, - } + EventHandle { counter: 0, guid } } #[deprecated] /// Emit an event with payload `msg` by using `handle_ref`'s key and counter. - public fun emit_event(handle_ref: &mut EventHandle, msg: T) { + public fun emit_event( + handle_ref: &mut EventHandle, msg: T + ) { write_to_event_store(bcs::to_bytes(&handle_ref.guid), handle_ref.counter, msg); spec { assume handle_ref.counter + 1 <= MAX_U64; @@ -71,7 +70,9 @@ module supra_framework::event { #[deprecated] /// Log `msg` as the `count`th event associated with the event stream identified by `guid` - native fun write_to_event_store(guid: vector, count: u64, msg: T); + native fun write_to_event_store( + guid: vector, count: u64, msg: T + ); #[deprecated] /// Destroy a unique handle. @@ -81,11 +82,15 @@ module supra_framework::event { #[deprecated] #[test_only] - public native fun emitted_events_by_handle(handle: &EventHandle): vector; + public native fun emitted_events_by_handle( + handle: &EventHandle + ): vector; #[deprecated] #[test_only] - public fun was_event_emitted_by_handle(handle: &EventHandle, msg: &T): bool { + public fun was_event_emitted_by_handle( + handle: &EventHandle, msg: &T + ): bool { use std::vector; vector::contains(&emitted_events_by_handle(handle), msg) } diff --git a/aptos-move/framework/supra-framework/sources/function_info.move b/aptos-move/framework/supra-framework/sources/function_info.move index f7da7eda99775..3d61b07b1acdf 100644 --- a/aptos-move/framework/supra-framework/sources/function_info.move +++ b/aptos-move/framework/supra-framework/sources/function_info.move @@ -19,26 +19,26 @@ module supra_framework::function_info { struct FunctionInfo has copy, drop, store { module_address: address, module_name: String, - function_name: String, + function_name: String } /// Creates a new function info from names. public fun new_function_info( module_signer: &signer, module_name: String, - function_name: String, + function_name: String ): FunctionInfo { new_function_info_from_address( signer::address_of(module_signer), module_name, - function_name, + function_name ) } public(friend) fun new_function_info_from_address( module_address: address, module_name: String, - function_name: String, + function_name: String ): FunctionInfo { assert!( is_identifier(string::bytes(&module_name)), @@ -48,11 +48,7 @@ module supra_framework::function_info { is_identifier(string::bytes(&function_name)), EINVALID_IDENTIFIER ); - FunctionInfo { - module_address, - module_name, - function_name, - } + FunctionInfo { module_address, module_name, function_name } } /// Check if the dispatch target function meets the type requirements of the disptach entry point. @@ -66,8 +62,7 @@ module supra_framework::function_info { /// /// dispatch_target also needs to be public so the type signature will remain unchanged. public(friend) fun check_dispatch_type_compatibility( - framework_function: &FunctionInfo, - dispatch_target: &FunctionInfo, + framework_function: &FunctionInfo, dispatch_target: &FunctionInfo ): bool { assert!( features::dispatchable_fungible_asset_enabled(), @@ -90,7 +85,9 @@ module supra_framework::function_info { load_function_impl(f) } - native fun check_dispatch_type_compatibility_impl(lhs: &FunctionInfo, r: &FunctionInfo): bool; + native fun check_dispatch_type_compatibility_impl( + lhs: &FunctionInfo, r: &FunctionInfo + ): bool; native fun is_identifier(s: &vector): bool; native fun load_function_impl(f: &FunctionInfo); diff --git a/aptos-move/framework/supra-framework/sources/function_info.spec.move b/aptos-move/framework/supra-framework/sources/function_info.spec.move index 01731ed43b014..1f8b1e2ccd463 100644 --- a/aptos-move/framework/supra-framework/sources/function_info.spec.move +++ b/aptos-move/framework/supra-framework/sources/function_info.spec.move @@ -7,7 +7,7 @@ spec supra_framework::function_info { pragma opaque; } - spec load_function_impl{ + spec load_function_impl { pragma opaque; } } diff --git a/aptos-move/framework/supra-framework/sources/fungible_asset.move b/aptos-move/framework/supra-framework/sources/fungible_asset.move index 966e73fcea509..da42dce1c7e84 100644 --- a/aptos-move/framework/supra-framework/sources/fungible_asset.move +++ b/aptos-move/framework/supra-framework/sources/fungible_asset.move @@ -102,12 +102,12 @@ module supra_framework::fungible_asset { struct Supply has key { current: u128, // option::none() means unlimited supply. - maximum: Option, + maximum: Option } #[resource_group_member(group = supra_framework::object::ObjectGroup)] struct ConcurrentSupply has key { - current: Aggregator, + current: Aggregator } #[resource_group_member(group = supra_framework::object::ObjectGroup)] @@ -126,7 +126,7 @@ module supra_framework::fungible_asset { /// asset. icon_uri: String, /// The Uniform Resource Identifier (uri) pointing to the website for the fungible asset. - project_uri: String, + project_uri: String } #[resource_group_member(group = supra_framework::object::ObjectGroup)] @@ -142,28 +142,28 @@ module supra_framework::fungible_asset { /// The balance of the fungible metadata. balance: u64, /// If true, owner transfer is disabled that only `TransferRef` can move in/out from this store. - frozen: bool, + frozen: bool } #[resource_group_member(group = supra_framework::object::ObjectGroup)] struct DispatchFunctionStore has key { - withdraw_function: Option, - deposit_function: Option, - derived_balance_function: Option, + withdraw_function: Option, + deposit_function: Option, + derived_balance_function: Option } #[resource_group_member(group = supra_framework::object::ObjectGroup)] /// The store object that holds concurrent fungible asset balance. struct ConcurrentFungibleBalance has key { /// The balance of the fungible metadata. - balance: Aggregator, + balance: Aggregator } /// FungibleAsset can be passed into function for type safety and to guarantee a specific amount. /// FungibleAsset is ephemeral and cannot be stored directly. It must be deposited back into a store. struct FungibleAsset { metadata: Object, - amount: u64, + amount: u64 } /// MintRef can be used to mint the fungible asset into an account's store. @@ -191,21 +191,21 @@ module supra_framework::fungible_asset { /// Emitted when fungible assets are deposited into a store. struct Deposit has drop, store { store: address, - amount: u64, + amount: u64 } #[event] /// Emitted when fungible assets are withdrawn from a store. struct Withdraw has drop, store { store: address, - amount: u64, + amount: u64 } #[event] /// Emitted when a store's frozen status is updated. struct Frozen has drop, store { store: address, - frozen: bool, + frozen: bool } inline fun default_to_concurrent_fungible_supply(): bool { @@ -234,39 +234,54 @@ module supra_framework::fungible_asset { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ): Object { - assert!(!object::can_generate_delete_ref(constructor_ref), error::invalid_argument(EOBJECT_IS_DELETABLE)); + assert!( + !object::can_generate_delete_ref(constructor_ref), + error::invalid_argument(EOBJECT_IS_DELETABLE) + ); let metadata_object_signer = &object::generate_signer(constructor_ref); - assert!(string::length(&name) <= MAX_NAME_LENGTH, error::out_of_range(ENAME_TOO_LONG)); - assert!(string::length(&symbol) <= MAX_SYMBOL_LENGTH, error::out_of_range(ESYMBOL_TOO_LONG)); + assert!( + string::length(&name) <= MAX_NAME_LENGTH, error::out_of_range(ENAME_TOO_LONG) + ); + assert!( + string::length(&symbol) <= MAX_SYMBOL_LENGTH, + error::out_of_range(ESYMBOL_TOO_LONG) + ); assert!(decimals <= MAX_DECIMALS, error::out_of_range(EDECIMALS_TOO_LARGE)); - assert!(string::length(&icon_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); - assert!(string::length(&project_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG)); - move_to(metadata_object_signer, - Metadata { - name, - symbol, - decimals, - icon_uri, - project_uri, - } + assert!( + string::length(&icon_uri) <= MAX_URI_LENGTH, error::out_of_range( + EURI_TOO_LONG + ) + ); + assert!( + string::length(&project_uri) <= MAX_URI_LENGTH, + error::out_of_range(EURI_TOO_LONG) + ); + move_to( + metadata_object_signer, + Metadata { name, symbol, decimals, icon_uri, project_uri } ); if (default_to_concurrent_fungible_supply()) { let unlimited = option::is_none(&maximum_supply); - move_to(metadata_object_signer, ConcurrentSupply { - current: if (unlimited) { - aggregator_v2::create_unbounded_aggregator() - } else { - aggregator_v2::create_aggregator(option::extract(&mut maximum_supply)) - }, - }); + move_to( + metadata_object_signer, + ConcurrentSupply { + current: if (unlimited) { + aggregator_v2::create_unbounded_aggregator() + } else { + aggregator_v2::create_aggregator( + option::extract(&mut maximum_supply) + ) + } + } + ); } else { - move_to(metadata_object_signer, Supply { - current: 0, - maximum: maximum_supply - }); + move_to( + metadata_object_signer, + Supply { current: 0, maximum: maximum_supply } + ); }; object::object_from_constructor_ref(constructor_ref) @@ -275,12 +290,15 @@ module supra_framework::fungible_asset { /// Set that only untransferable stores can be created for this fungible asset. public fun set_untransferable(constructor_ref: &ConstructorRef) { let metadata_addr = object::address_from_constructor_ref(constructor_ref); - assert!(exists(metadata_addr), error::not_found(EFUNGIBLE_METADATA_EXISTENCE)); + assert!( + exists(metadata_addr), error::not_found( + EFUNGIBLE_METADATA_EXISTENCE + ) + ); let metadata_signer = &object::generate_signer(constructor_ref); move_to(metadata_signer, Untransferable {}); } - #[view] /// Returns true if the FA is untransferable. public fun is_untransferable(metadata: Object): bool { @@ -292,66 +310,75 @@ module supra_framework::fungible_asset { constructor_ref: &ConstructorRef, withdraw_function: Option, deposit_function: Option, - derived_balance_function: Option, + derived_balance_function: Option ) { // Verify that caller type matches callee type so wrongly typed function cannot be registered. - option::for_each_ref(&withdraw_function, |withdraw_function| { - let dispatcher_withdraw_function_info = function_info::new_function_info_from_address( - @supra_framework, - string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_withdraw"), - ); + option::for_each_ref( + &withdraw_function, + |withdraw_function| { + let dispatcher_withdraw_function_info = + function_info::new_function_info_from_address( + @supra_framework, + string::utf8(b"dispatchable_fungible_asset"), + string::utf8(b"dispatchable_withdraw") + ); - assert!( - function_info::check_dispatch_type_compatibility( - &dispatcher_withdraw_function_info, - withdraw_function - ), - error::invalid_argument( - EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH - ) - ); - }); + assert!( + function_info::check_dispatch_type_compatibility( + &dispatcher_withdraw_function_info, + withdraw_function + ), + error::invalid_argument(EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH) + ); + } + ); - option::for_each_ref(&deposit_function, |deposit_function| { - let dispatcher_deposit_function_info = function_info::new_function_info_from_address( - @supra_framework, - string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_deposit"), - ); - // Verify that caller type matches callee type so wrongly typed function cannot be registered. - assert!( - function_info::check_dispatch_type_compatibility( - &dispatcher_deposit_function_info, - deposit_function - ), - error::invalid_argument( - EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH - ) - ); - }); + option::for_each_ref( + &deposit_function, + |deposit_function| { + let dispatcher_deposit_function_info = + function_info::new_function_info_from_address( + @supra_framework, + string::utf8(b"dispatchable_fungible_asset"), + string::utf8(b"dispatchable_deposit") + ); + // Verify that caller type matches callee type so wrongly typed function cannot be registered. + assert!( + function_info::check_dispatch_type_compatibility( + &dispatcher_deposit_function_info, + deposit_function + ), + error::invalid_argument(EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH) + ); + } + ); - option::for_each_ref(&derived_balance_function, |balance_function| { - let dispatcher_derived_balance_function_info = function_info::new_function_info_from_address( - @supra_framework, - string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_derived_balance"), - ); - // Verify that caller type matches callee type so wrongly typed function cannot be registered. - assert!( - function_info::check_dispatch_type_compatibility( - &dispatcher_derived_balance_function_info, - balance_function - ), - error::invalid_argument( - EDERIVED_BALANCE_FUNCTION_SIGNATURE_MISMATCH - ) - ); - }); + option::for_each_ref( + &derived_balance_function, + |balance_function| { + let dispatcher_derived_balance_function_info = + function_info::new_function_info_from_address( + @supra_framework, + string::utf8(b"dispatchable_fungible_asset"), + string::utf8(b"dispatchable_derived_balance") + ); + // Verify that caller type matches callee type so wrongly typed function cannot be registered. + assert!( + function_info::check_dispatch_type_compatibility( + &dispatcher_derived_balance_function_info, + balance_function + ), + error::invalid_argument( + EDERIVED_BALANCE_FUNCTION_SIGNATURE_MISMATCH + ) + ); + } + ); // Cannot register hook for SUPRA. assert!( - object::address_from_constructor_ref(constructor_ref) != @aptos_fungible_asset, + object::address_from_constructor_ref(constructor_ref) + != @aptos_fungible_asset, error::permission_denied(EAPT_NOT_DISPATCHABLE) ); assert!( @@ -365,10 +392,8 @@ module supra_framework::fungible_asset { error::already_exists(EALREADY_REGISTERED) ); assert!( - exists( - object::address_from_constructor_ref(constructor_ref) - ), - error::not_found(EFUNGIBLE_METADATA_EXISTENCE), + exists(object::address_from_constructor_ref(constructor_ref)), + error::not_found(EFUNGIBLE_METADATA_EXISTENCE) ); let store_obj = &object::generate_signer(constructor_ref); @@ -379,7 +404,7 @@ module supra_framework::fungible_asset { DispatchFunctionStore { withdraw_function, deposit_function, - derived_balance_function, + derived_balance_function } ); } @@ -409,7 +434,9 @@ module supra_framework::fungible_asset { /// Creates a mutate metadata ref that can be used to change the metadata information of fungible assets from the /// given fungible object's constructor ref. /// This can only be called at object creation time as constructor_ref is only available then. - public fun generate_mutate_metadata_ref(constructor_ref: &ConstructorRef): MutateMetadataRef { + public fun generate_mutate_metadata_ref( + constructor_ref: &ConstructorRef + ): MutateMetadataRef { let metadata = object::object_from_constructor_ref(constructor_ref); MutateMetadataRef { metadata } } @@ -521,34 +548,42 @@ module supra_framework::fungible_asset { #[view] /// Get the balance of a given store. - public fun balance(store: Object): u64 acquires FungibleStore, ConcurrentFungibleBalance { + public fun balance( + store: Object + ): u64 acquires FungibleStore, ConcurrentFungibleBalance { let store_addr = object::object_address(&store); if (store_exists_inline(store_addr)) { let store_balance = borrow_store_resource(&store).balance; - if (store_balance == 0 && concurrent_fungible_balance_exists_inline(store_addr)) { - let balance_resource = borrow_global(store_addr); + if (store_balance == 0 + && concurrent_fungible_balance_exists_inline(store_addr)) { + let balance_resource = + borrow_global(store_addr); aggregator_v2::read(&balance_resource.balance) } else { store_balance } - } else { - 0 - } + } else { 0 } } #[view] /// Check whether the balance of a given store is >= `amount`. - public fun is_balance_at_least(store: Object, amount: u64): bool acquires FungibleStore, ConcurrentFungibleBalance { + public fun is_balance_at_least( + store: Object, amount: u64 + ): bool acquires FungibleStore, ConcurrentFungibleBalance { let store_addr = object::object_address(&store); is_address_balance_at_least(store_addr, amount) } /// Check whether the balance of a given store is >= `amount`. - public(friend) fun is_address_balance_at_least(store_addr: address, amount: u64): bool acquires FungibleStore, ConcurrentFungibleBalance { + public(friend) fun is_address_balance_at_least( + store_addr: address, amount: u64 + ): bool acquires FungibleStore, ConcurrentFungibleBalance { if (store_exists_inline(store_addr)) { let store_balance = borrow_global(store_addr).balance; - if (store_balance == 0 && concurrent_fungible_balance_exists_inline(store_addr)) { - let balance_resource = borrow_global(store_addr); + if (store_balance == 0 + && concurrent_fungible_balance_exists_inline(store_addr)) { + let balance_resource = + borrow_global(store_addr); aggregator_v2::is_at_least(&balance_resource.balance, amount) } else { store_balance >= amount @@ -564,7 +599,8 @@ module supra_framework::fungible_asset { /// If the store has not been created, we default to returning false so deposits can be sent to it. public fun is_frozen(store: Object): bool acquires FungibleStore { let store_addr = object::object_address(&store); - store_exists_inline(store_addr) && borrow_global(store_addr).frozen + store_exists_inline(store_addr) + && borrow_global(store_addr).frozen } #[view] @@ -575,47 +611,59 @@ module supra_framework::fungible_asset { exists(metadata_addr) } - public fun deposit_dispatch_function(store: Object): Option acquires FungibleStore, DispatchFunctionStore { + public fun deposit_dispatch_function( + store: Object + ): Option acquires FungibleStore, DispatchFunctionStore { let fa_store = borrow_store_resource(&store); let metadata_addr = object::object_address(&fa_store.metadata); - if(exists(metadata_addr)) { + if (exists(metadata_addr)) { borrow_global(metadata_addr).deposit_function } else { option::none() } } - fun has_deposit_dispatch_function(metadata: Object): bool acquires DispatchFunctionStore { + fun has_deposit_dispatch_function( + metadata: Object + ): bool acquires DispatchFunctionStore { let metadata_addr = object::object_address(&metadata); // Short circuit on SUPRA for better perf - if(metadata_addr != @aptos_fungible_asset && exists(metadata_addr)) { - option::is_some(&borrow_global(metadata_addr).deposit_function) - } else { - false - } + if (metadata_addr != @aptos_fungible_asset + && exists(metadata_addr)) { + option::is_some( + &borrow_global(metadata_addr).deposit_function + ) + } else { false } } - public fun withdraw_dispatch_function(store: Object): Option acquires FungibleStore, DispatchFunctionStore { + public fun withdraw_dispatch_function( + store: Object + ): Option acquires FungibleStore, DispatchFunctionStore { let fa_store = borrow_store_resource(&store); let metadata_addr = object::object_address(&fa_store.metadata); - if(exists(metadata_addr)) { + if (exists(metadata_addr)) { borrow_global(metadata_addr).withdraw_function } else { option::none() } } - fun has_withdraw_dispatch_function(metadata: Object): bool acquires DispatchFunctionStore { + fun has_withdraw_dispatch_function( + metadata: Object + ): bool acquires DispatchFunctionStore { let metadata_addr = object::object_address(&metadata); // Short circuit on SUPRA for better perf - if (metadata_addr != @aptos_fungible_asset && exists(metadata_addr)) { - option::is_some(&borrow_global(metadata_addr).withdraw_function) - } else { - false - } + if (metadata_addr != @aptos_fungible_asset + && exists(metadata_addr)) { + option::is_some( + &borrow_global(metadata_addr).withdraw_function + ) + } else { false } } - public(friend) fun derived_balance_dispatch_function(store: Object): Option acquires FungibleStore, DispatchFunctionStore { + public(friend) fun derived_balance_dispatch_function( + store: Object + ): Option acquires FungibleStore, DispatchFunctionStore { let fa_store = borrow_store_resource(&store); let metadata_addr = object::object_address(&fa_store.metadata); if (exists(metadata_addr)) { @@ -655,7 +703,7 @@ module supra_framework::fungible_asset { sender: &signer, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires FungibleStore, DispatchFunctionStore, ConcurrentFungibleBalance { let fa = withdraw(sender, from, amount); deposit(to, fa); @@ -664,49 +712,57 @@ module supra_framework::fungible_asset { /// Allow an object to hold a store for fungible assets. /// Applications can use this to create multiple stores for isolating fungible assets for different purposes. public fun create_store( - constructor_ref: &ConstructorRef, - metadata: Object, + constructor_ref: &ConstructorRef, metadata: Object ): Object { let store_obj = &object::generate_signer(constructor_ref); - move_to(store_obj, FungibleStore { - metadata: object::convert(metadata), - balance: 0, - frozen: false, - }); + move_to( + store_obj, + FungibleStore { + metadata: object::convert(metadata), + balance: 0, + frozen: false + } + ); if (is_untransferable(metadata)) { object::set_untransferable(constructor_ref); }; if (default_to_concurrent_fungible_balance()) { - move_to(store_obj, ConcurrentFungibleBalance { - balance: aggregator_v2::create_unbounded_aggregator(), - }); + move_to( + store_obj, + ConcurrentFungibleBalance { + balance: aggregator_v2::create_unbounded_aggregator() + } + ); }; object::object_from_constructor_ref(constructor_ref) } /// Used to delete a store. Requires the store to be completely empty prior to removing it - public fun remove_store(delete_ref: &DeleteRef) acquires FungibleStore, FungibleAssetEvents, ConcurrentFungibleBalance { + public fun remove_store( + delete_ref: &DeleteRef + ) acquires FungibleStore, FungibleAssetEvents, ConcurrentFungibleBalance { let store = &object::object_from_delete_ref(delete_ref); let addr = object::object_address(store); - let FungibleStore { metadata: _, balance, frozen: _ } - = move_from(addr); + let FungibleStore { metadata: _, balance, frozen: _ } = + move_from(addr); assert!(balance == 0, error::permission_denied(EBALANCE_IS_NOT_ZERO)); if (concurrent_fungible_balance_exists_inline(addr)) { - let ConcurrentFungibleBalance { balance } = move_from(addr); - assert!(aggregator_v2::read(&balance) == 0, error::permission_denied(EBALANCE_IS_NOT_ZERO)); + let ConcurrentFungibleBalance { balance } = + move_from(addr); + assert!( + aggregator_v2::read(&balance) == 0, + error::permission_denied(EBALANCE_IS_NOT_ZERO) + ); }; // Cleanup deprecated event handles if exist. if (exists(addr)) { - let FungibleAssetEvents { - deposit_events, - withdraw_events, - frozen_events, - } = move_from(addr); + let FungibleAssetEvents { deposit_events, withdraw_events, frozen_events } = + move_from(addr); event::destroy_handle(deposit_events); event::destroy_handle(withdraw_events); event::destroy_handle(frozen_events); @@ -717,7 +773,7 @@ module supra_framework::fungible_asset { public fun withdraw( owner: &signer, store: Object, - amount: u64, + amount: u64 ): FungibleAsset acquires FungibleStore, DispatchFunctionStore, ConcurrentFungibleBalance { withdraw_sanity_check(owner, store, true); withdraw_internal(object::object_address(&store), amount) @@ -727,9 +783,12 @@ module supra_framework::fungible_asset { public(friend) fun withdraw_sanity_check( owner: &signer, store: Object, - abort_on_dispatch: bool, + abort_on_dispatch: bool ) acquires FungibleStore, DispatchFunctionStore { - assert!(object::owns(store, signer::address_of(owner)), error::permission_denied(ENOT_STORE_OWNER)); + assert!( + object::owns(store, signer::address_of(owner)), + error::permission_denied(ENOT_STORE_OWNER) + ); let fa_store = borrow_store_resource(&store); assert!( !abort_on_dispatch || !has_withdraw_dispatch_function(fa_store.metadata), @@ -740,8 +799,7 @@ module supra_framework::fungible_asset { /// Deposit `amount` of the fungible asset to `store`. public fun deposit_sanity_check( - store: Object, - abort_on_dispatch: bool + store: Object, abort_on_dispatch: bool ) acquires FungibleStore, DispatchFunctionStore { let fa_store = borrow_store_resource(&store); assert!( @@ -752,7 +810,9 @@ module supra_framework::fungible_asset { } /// Deposit `amount` of the fungible asset to `store`. - public fun deposit(store: Object, fa: FungibleAsset) acquires FungibleStore, DispatchFunctionStore, ConcurrentFungibleBalance { + public fun deposit( + store: Object, fa: FungibleAsset + ) acquires FungibleStore, DispatchFunctionStore, ConcurrentFungibleBalance { deposit_sanity_check(store, true); deposit_internal(object::object_address(&store), fa); } @@ -765,19 +825,16 @@ module supra_framework::fungible_asset { /// CAN ONLY BE CALLED BY coin.move for migration. public(friend) fun mint_internal( - metadata: Object, - amount: u64 + metadata: Object, amount: u64 ): FungibleAsset acquires Supply, ConcurrentSupply { increase_supply(&metadata, amount); - FungibleAsset { - metadata, - amount - } + FungibleAsset { metadata, amount } } /// Mint the specified `amount` of the fungible asset to a destination store. - public fun mint_to(ref: &MintRef, store: Object, amount: u64) - acquires FungibleStore, Supply, ConcurrentSupply, DispatchFunctionStore, ConcurrentFungibleBalance { + public fun mint_to( + ref: &MintRef, store: Object, amount: u64 + ) acquires FungibleStore, Supply, ConcurrentSupply, DispatchFunctionStore, ConcurrentFungibleBalance { deposit_sanity_check(store, false); deposit_internal(object::object_address(&store), mint(ref, amount)); } @@ -786,18 +843,17 @@ module supra_framework::fungible_asset { public fun set_frozen_flag( ref: &TransferRef, store: Object, - frozen: bool, + frozen: bool ) acquires FungibleStore { assert!( ref.metadata == store_metadata(store), - error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH), + error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH) ); set_frozen_flag_internal(store, frozen) } public(friend) fun set_frozen_flag_internal( - store: Object, - frozen: bool + store: Object, frozen: bool ) acquires FungibleStore { let store_addr = object::object_address(&store); borrow_global_mut(store_addr).frozen = frozen; @@ -815,31 +871,22 @@ module supra_framework::fungible_asset { } /// CAN ONLY BE CALLED BY coin.move for migration. - public(friend) fun burn_internal( - fa: FungibleAsset - ): u64 acquires Supply, ConcurrentSupply { - let FungibleAsset { - metadata, - amount - } = fa; + public(friend) fun burn_internal(fa: FungibleAsset): u64 acquires Supply, ConcurrentSupply { + let FungibleAsset { metadata, amount } = fa; decrease_supply(&metadata, amount); amount } /// Burn the `amount` of the fungible asset from the given store. public fun burn_from( - ref: &BurnRef, - store: Object, - amount: u64 + ref: &BurnRef, store: Object, amount: u64 ) acquires FungibleStore, Supply, ConcurrentSupply, ConcurrentFungibleBalance { // ref metadata match is checked in burn() call burn(ref, withdraw_internal(object::object_address(&store), amount)); } public(friend) fun address_burn_from( - ref: &BurnRef, - store_addr: address, - amount: u64 + ref: &BurnRef, store_addr: address, amount: u64 ) acquires FungibleStore, Supply, ConcurrentSupply, ConcurrentFungibleBalance { // ref metadata match is checked in burn() call burn(ref, withdraw_internal(store_addr, amount)); @@ -847,22 +894,18 @@ module supra_framework::fungible_asset { /// Withdraw `amount` of the fungible asset from the `store` ignoring `frozen`. public fun withdraw_with_ref( - ref: &TransferRef, - store: Object, - amount: u64 + ref: &TransferRef, store: Object, amount: u64 ): FungibleAsset acquires FungibleStore, ConcurrentFungibleBalance { assert!( ref.metadata == store_metadata(store), - error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH), + error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH) ); withdraw_internal(object::object_address(&store), amount) } /// Deposit the fungible asset into the `store` ignoring `frozen`. public fun deposit_with_ref( - ref: &TransferRef, - store: Object, - fa: FungibleAsset + ref: &TransferRef, store: Object, fa: FungibleAsset ) acquires FungibleStore, ConcurrentFungibleBalance { assert!( ref.metadata == fa.metadata, @@ -876,7 +919,7 @@ module supra_framework::fungible_asset { transfer_ref: &TransferRef, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires FungibleStore, ConcurrentFungibleBalance { let fa = withdraw_with_ref(transfer_ref, from, amount); deposit_with_ref(transfer_ref, to, fa); @@ -889,24 +932,24 @@ module supra_framework::fungible_asset { symbol: Option, decimals: Option, icon_uri: Option, - project_uri: Option, + project_uri: Option ) acquires Metadata { let metadata_address = object::object_address(&metadata_ref.metadata); let mutable_metadata = borrow_global_mut(metadata_address); - if (option::is_some(&name)){ + if (option::is_some(&name)) { mutable_metadata.name = option::extract(&mut name); }; - if (option::is_some(&symbol)){ + if (option::is_some(&symbol)) { mutable_metadata.symbol = option::extract(&mut symbol); }; - if (option::is_some(&decimals)){ + if (option::is_some(&decimals)) { mutable_metadata.decimals = option::extract(&mut decimals); }; - if (option::is_some(&icon_uri)){ + if (option::is_some(&icon_uri)) { mutable_metadata.icon_uri = option::extract(&mut icon_uri); }; - if (option::is_some(&project_uri)){ + if (option::is_some(&project_uri)) { mutable_metadata.project_uri = option::extract(&mut project_uri); }; } @@ -914,27 +957,30 @@ module supra_framework::fungible_asset { /// Create a fungible asset with zero amount. /// This can be useful when starting a series of computations where the initial value is 0. public fun zero(metadata: Object): FungibleAsset { - FungibleAsset { - metadata: object::convert(metadata), - amount: 0, - } + FungibleAsset { metadata: object::convert(metadata), amount: 0 } } /// Extract a given amount from the given fungible asset and return a new one. public fun extract(fungible_asset: &mut FungibleAsset, amount: u64): FungibleAsset { - assert!(fungible_asset.amount >= amount, error::invalid_argument(EINSUFFICIENT_BALANCE)); + assert!( + fungible_asset.amount >= amount, error::invalid_argument( + EINSUFFICIENT_BALANCE + ) + ); fungible_asset.amount = fungible_asset.amount - amount; - FungibleAsset { - metadata: fungible_asset.metadata, - amount, - } + FungibleAsset { metadata: fungible_asset.metadata, amount } } /// "Merges" the two given fungible assets. The fungible asset passed in as `dst_fungible_asset` will have a value /// equal to the sum of the two (`dst_fungible_asset` and `src_fungible_asset`). - public fun merge(dst_fungible_asset: &mut FungibleAsset, src_fungible_asset: FungibleAsset) { + public fun merge( + dst_fungible_asset: &mut FungibleAsset, src_fungible_asset: FungibleAsset + ) { let FungibleAsset { metadata, amount } = src_fungible_asset; - assert!(metadata == dst_fungible_asset.metadata, error::invalid_argument(EFUNGIBLE_ASSET_MISMATCH)); + assert!( + metadata == dst_fungible_asset.metadata, + error::invalid_argument(EFUNGIBLE_ASSET_MISMATCH) + ); dst_fungible_asset.amount = dst_fungible_asset.amount + amount; } @@ -944,16 +990,24 @@ module supra_framework::fungible_asset { assert!(amount == 0, error::invalid_argument(EAMOUNT_IS_NOT_ZERO)); } - public(friend) fun deposit_internal(store_addr: address, fa: FungibleAsset) acquires FungibleStore, ConcurrentFungibleBalance { + public(friend) fun deposit_internal( + store_addr: address, fa: FungibleAsset + ) acquires FungibleStore, ConcurrentFungibleBalance { let FungibleAsset { metadata, amount } = fa; - assert!(exists(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE)); + assert!( + exists(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE) + ); let store = borrow_global_mut(store_addr); - assert!(metadata == store.metadata, error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH)); + assert!( + metadata == store.metadata, + error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH) + ); if (amount == 0) return; if (store.balance == 0 && concurrent_fungible_balance_exists_inline(store_addr)) { - let balance_resource = borrow_global_mut(store_addr); + let balance_resource = + borrow_global_mut(store_addr); aggregator_v2::add(&mut balance_resource.balance, amount); } else { store.balance = store.balance + amount; @@ -964,22 +1018,29 @@ module supra_framework::fungible_asset { /// Extract `amount` of the fungible asset from `store`. public(friend) fun withdraw_internal( - store_addr: address, - amount: u64, + store_addr: address, amount: u64 ): FungibleAsset acquires FungibleStore, ConcurrentFungibleBalance { - assert!(exists(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE)); + assert!( + exists(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE) + ); let store = borrow_global_mut(store_addr); let metadata = store.metadata; if (amount != 0) { - if (store.balance == 0 && concurrent_fungible_balance_exists_inline(store_addr)) { - let balance_resource = borrow_global_mut(store_addr); + if (store.balance == 0 + && concurrent_fungible_balance_exists_inline(store_addr)) { + let balance_resource = + borrow_global_mut(store_addr); assert!( aggregator_v2::try_sub(&mut balance_resource.balance, amount), error::invalid_argument(EINSUFFICIENT_BALANCE) ); } else { - assert!(store.balance >= amount, error::invalid_argument(EINSUFFICIENT_BALANCE)); + assert!( + store.balance >= amount, error::invalid_argument( + EINSUFFICIENT_BALANCE + ) + ); store.balance = store.balance - amount; }; @@ -990,9 +1051,7 @@ module supra_framework::fungible_asset { /// Increase the supply of a fungible asset by minting. fun increase_supply(metadata: &Object, amount: u64) acquires Supply, ConcurrentSupply { - if (amount == 0) { - return - }; + if (amount == 0) { return }; let metadata_address = object::object_address(metadata); if (exists(metadata_address)) { @@ -1018,9 +1077,7 @@ module supra_framework::fungible_asset { /// Decrease the supply of a fungible asset by burning. fun decrease_supply(metadata: &Object, amount: u64) acquires Supply, ConcurrentSupply { - if (amount == 0) { - return - }; + if (amount == 0) { return }; let metadata_address = object::object_address(metadata); if (exists(metadata_address)) { @@ -1043,9 +1100,7 @@ module supra_framework::fungible_asset { } } - inline fun borrow_fungible_metadata( - metadata: &Object - ): &Metadata acquires Metadata { + inline fun borrow_fungible_metadata(metadata: &Object): &Metadata acquires Metadata { let addr = object::object_address(metadata); borrow_global(addr) } @@ -1057,58 +1112,64 @@ module supra_framework::fungible_asset { borrow_global_mut(addr) } - inline fun borrow_store_resource(store: &Object): &FungibleStore acquires FungibleStore { + inline fun borrow_store_resource( + store: &Object + ): &FungibleStore acquires FungibleStore { let store_addr = object::object_address(store); - assert!(exists(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE)); + assert!( + exists(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE) + ); borrow_global(store_addr) } - public fun upgrade_to_concurrent( - ref: &ExtendRef, - ) acquires Supply { + public fun upgrade_to_concurrent(ref: &ExtendRef) acquires Supply { let metadata_object_address = object::address_from_extend_ref(ref); let metadata_object_signer = object::generate_signer_for_extending(ref); assert!( features::concurrent_fungible_assets_enabled(), error::invalid_argument(ECONCURRENT_SUPPLY_NOT_ENABLED) ); - assert!(exists(metadata_object_address), error::not_found(ESUPPLY_NOT_FOUND)); - let Supply { - current, - maximum, - } = move_from(metadata_object_address); + assert!( + exists(metadata_object_address), error::not_found(ESUPPLY_NOT_FOUND) + ); + let Supply { current, maximum } = move_from(metadata_object_address); let unlimited = option::is_none(&maximum); let supply = ConcurrentSupply { current: if (unlimited) { aggregator_v2::create_unbounded_aggregator_with_value(current) + } else { + aggregator_v2::create_aggregator_with_value( + current, option::extract(&mut maximum) + ) } - else { - aggregator_v2::create_aggregator_with_value(current, option::extract(&mut maximum)) - }, }; move_to(&metadata_object_signer, supply); } public entry fun upgrade_store_to_concurrent( - owner: &signer, - store: Object, + owner: &signer, store: Object ) acquires FungibleStore { - assert!(object::owns(store, signer::address_of(owner)), error::permission_denied(ENOT_STORE_OWNER)); + assert!( + object::owns(store, signer::address_of(owner)), + error::permission_denied(ENOT_STORE_OWNER) + ); assert!(!is_frozen(store), error::invalid_argument(ESTORE_IS_FROZEN)); - assert!(allow_upgrade_to_concurrent_fungible_balance(), error::invalid_argument(ECONCURRENT_BALANCE_NOT_ENABLED)); + assert!( + allow_upgrade_to_concurrent_fungible_balance(), + error::invalid_argument(ECONCURRENT_BALANCE_NOT_ENABLED) + ); ensure_store_upgraded_to_concurrent_internal(object::object_address(&store)); } /// Ensure a known `FungibleStore` has `ConcurrentFungibleBalance`. fun ensure_store_upgraded_to_concurrent_internal( - fungible_store_address: address, + fungible_store_address: address ) acquires FungibleStore { - if (exists(fungible_store_address)) { - return - }; + if (exists(fungible_store_address)) { return }; let store = borrow_global_mut(fungible_store_address); - let balance = aggregator_v2::create_unbounded_aggregator_with_value(store.balance); + let balance = + aggregator_v2::create_unbounded_aggregator_with_value(store.balance); store.balance = 0; let object_signer = create_signer::create_signer(fungible_store_address); move_to(&object_signer, ConcurrentFungibleBalance { balance }); @@ -1134,7 +1195,9 @@ module supra_framework::fungible_asset { } #[test_only] - public fun init_test_metadata(constructor_ref: &ConstructorRef): (MintRef, TransferRef, BurnRef, MutateMetadataRef) { + public fun init_test_metadata( + constructor_ref: &ConstructorRef + ): (MintRef, TransferRef, BurnRef, MutateMetadataRef) { add_fungibility( constructor_ref, option::some(100) /* max supply */, @@ -1142,12 +1205,12 @@ module supra_framework::fungible_asset { string::utf8(b"@@"), 0, string::utf8(b"http://www.example.com/favicon.ico"), - string::utf8(b"http://www.example.com"), + string::utf8(b"http://www.example.com") ); let mint_ref = generate_mint_ref(constructor_ref); let burn_ref = generate_burn_ref(constructor_ref); let transfer_ref = generate_transfer_ref(constructor_ref); - let mutate_metadata_ref= generate_mutate_metadata_ref(constructor_ref); + let mutate_metadata_ref = generate_mutate_metadata_ref(constructor_ref); (mint_ref, transfer_ref, burn_ref, mutate_metadata_ref) } @@ -1161,7 +1224,9 @@ module supra_framework::fungible_asset { } #[test_only] - public fun create_test_store(owner: &signer, metadata: Object): Object { + public fun create_test_store( + owner: &signer, metadata: Object + ): Object { let owner_addr = signer::address_of(owner); if (!account::exists_at(owner_addr)) { account::create_account_for_test(owner_addr); @@ -1178,16 +1243,22 @@ module supra_framework::fungible_asset { assert!(name(metadata) == string::utf8(b"TEST"), 3); assert!(symbol(metadata) == string::utf8(b"@@"), 4); assert!(decimals(metadata) == 0, 5); - assert!(icon_uri(metadata) == string::utf8(b"http://www.example.com/favicon.ico"), 6); + assert!( + icon_uri(metadata) == string::utf8(b"http://www.example.com/favicon.ico"), 6 + ); assert!(project_uri(metadata) == string::utf8(b"http://www.example.com"), 7); - assert!(metadata(metadata) == Metadata { - name: string::utf8(b"TEST"), - symbol: string::utf8(b"@@"), - decimals: 0, - icon_uri: string::utf8(b"http://www.example.com/favicon.ico"), - project_uri: string::utf8(b"http://www.example.com"), - }, 8); + assert!( + metadata(metadata) + == Metadata { + name: string::utf8(b"TEST"), + symbol: string::utf8(b"@@"), + decimals: 0, + icon_uri: string::utf8(b"http://www.example.com/favicon.ico"), + project_uri: string::utf8(b"http://www.example.com") + }, + 8 + ); increase_supply(&metadata, 50); assert!(supply(metadata) == option::some(50), 9); @@ -1204,7 +1275,9 @@ module supra_framework::fungible_asset { } #[test(creator = @0xcafe)] - fun test_create_and_remove_store(creator: &signer) acquires FungibleStore, FungibleAssetEvents, ConcurrentFungibleBalance { + fun test_create_and_remove_store( + creator: &signer + ) acquires FungibleStore, FungibleAssetEvents, ConcurrentFungibleBalance { let (_, _, _, _, metadata) = create_fungible_asset(creator); let creator_ref = object::create_object_from_account(creator); create_store(&creator_ref, metadata); @@ -1214,10 +1287,10 @@ module supra_framework::fungible_asset { #[test(creator = @0xcafe, aaron = @0xface)] fun test_e2e_basic_flow( - creator: &signer, - aaron: &signer, + creator: &signer, aaron: &signer ) acquires FungibleStore, Supply, ConcurrentSupply, DispatchFunctionStore, ConcurrentFungibleBalance, Metadata { - let (mint_ref, transfer_ref, burn_ref, mutate_metadata_ref, test_token) = create_fungible_asset(creator); + let (mint_ref, transfer_ref, burn_ref, mutate_metadata_ref, test_token) = + create_fungible_asset(creator); let metadata = mint_ref.metadata; let creator_store = create_test_store(creator, metadata); let aaron_store = create_test_store(aaron, metadata); @@ -1254,7 +1327,9 @@ module supra_framework::fungible_asset { assert!(name(metadata) == string::utf8(b"mutated_name"), 8); assert!(symbol(metadata) == string::utf8(b"mutated_symbol"), 9); assert!(decimals(metadata) == 0, 10); - assert!(icon_uri(metadata) == string::utf8(b"http://www.example.com/favicon.ico"), 11); + assert!( + icon_uri(metadata) == string::utf8(b"http://www.example.com/favicon.ico"), 11 + ); assert!(project_uri(metadata) == string::utf8(b"http://www.example.com"), 12); } @@ -1263,7 +1338,8 @@ module supra_framework::fungible_asset { fun test_frozen( creator: &signer ) acquires FungibleStore, Supply, ConcurrentSupply, DispatchFunctionStore, ConcurrentFungibleBalance { - let (mint_ref, transfer_ref, _burn_ref, _mutate_metadata_ref, _) = create_fungible_asset(creator); + let (mint_ref, transfer_ref, _burn_ref, _mutate_metadata_ref, _) = + create_fungible_asset(creator); let creator_store = create_test_store(creator, mint_ref.metadata); let fa = mint(&mint_ref, 100); @@ -1276,7 +1352,8 @@ module supra_framework::fungible_asset { fun test_mint_to_frozen( creator: &signer ) acquires FungibleStore, ConcurrentFungibleBalance, Supply, ConcurrentSupply, DispatchFunctionStore { - let (mint_ref, transfer_ref, _burn_ref, _mutate_metadata_ref, _) = create_fungible_asset(creator); + let (mint_ref, transfer_ref, _burn_ref, _mutate_metadata_ref, _) = + create_fungible_asset(creator); let creator_store = create_test_store(creator, mint_ref.metadata); set_frozen_flag(&transfer_ref, creator_store, true); @@ -1285,9 +1362,7 @@ module supra_framework::fungible_asset { #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x50003, location = supra_framework::object)] - fun test_untransferable( - creator: &signer - ) { + fun test_untransferable(creator: &signer) { let (creator_ref, _) = create_test_token(creator); let (mint_ref, _, _, _) = init_test_metadata(&creator_ref); set_untransferable(&creator_ref); @@ -1298,10 +1373,10 @@ module supra_framework::fungible_asset { #[test(creator = @0xcafe, aaron = @0xface)] fun test_transfer_with_ref( - creator: &signer, - aaron: &signer, + creator: &signer, aaron: &signer ) acquires FungibleStore, Supply, ConcurrentSupply, ConcurrentFungibleBalance { - let (mint_ref, transfer_ref, _burn_ref, _mutate_metadata_ref, _) = create_fungible_asset(creator); + let (mint_ref, transfer_ref, _burn_ref, _mutate_metadata_ref, _) = + create_fungible_asset(creator); let metadata = mint_ref.metadata; let creator_store = create_test_store(creator, metadata); let aaron_store = create_test_store(aaron, metadata); @@ -1318,10 +1393,9 @@ module supra_framework::fungible_asset { } #[test(creator = @0xcafe)] - fun test_mutate_metadata( - creator: &signer - ) acquires Metadata { - let (mint_ref, _transfer_ref, _burn_ref, mutate_metadata_ref, _) = create_fungible_asset(creator); + fun test_mutate_metadata(creator: &signer) acquires Metadata { + let (mint_ref, _transfer_ref, _burn_ref, mutate_metadata_ref, _) = + create_fungible_asset(creator); let metadata = mint_ref.metadata; mutate_metadata( @@ -1335,15 +1409,20 @@ module supra_framework::fungible_asset { assert!(name(metadata) == string::utf8(b"mutated_name"), 1); assert!(symbol(metadata) == string::utf8(b"mutated_symbol"), 2); assert!(decimals(metadata) == 10, 3); - assert!(icon_uri(metadata) == string::utf8(b"http://www.mutated-example.com/favicon.ico"), 4); - assert!(project_uri(metadata) == string::utf8(b"http://www.mutated-example.com"), 5); + assert!( + icon_uri(metadata) + == string::utf8(b"http://www.mutated-example.com/favicon.ico"), + 4 + ); + assert!( + project_uri(metadata) == string::utf8(b"http://www.mutated-example.com"), 5 + ); } #[test(creator = @0xcafe)] - fun test_partial_mutate_metadata( - creator: &signer - ) acquires Metadata { - let (mint_ref, _transfer_ref, _burn_ref, mutate_metadata_ref, _) = create_fungible_asset(creator); + fun test_partial_mutate_metadata(creator: &signer) acquires Metadata { + let (mint_ref, _transfer_ref, _burn_ref, mutate_metadata_ref, _) = + create_fungible_asset(creator); let metadata = mint_ref.metadata; mutate_metadata( @@ -1357,13 +1436,16 @@ module supra_framework::fungible_asset { assert!(name(metadata) == string::utf8(b"mutated_name"), 8); assert!(symbol(metadata) == string::utf8(b"mutated_symbol"), 9); assert!(decimals(metadata) == 0, 10); - assert!(icon_uri(metadata) == string::utf8(b"http://www.example.com/favicon.ico"), 11); + assert!( + icon_uri(metadata) == string::utf8(b"http://www.example.com/favicon.ico"), 11 + ); assert!(project_uri(metadata) == string::utf8(b"http://www.example.com"), 12); } #[test(creator = @0xcafe)] fun test_merge_and_exact(creator: &signer) acquires Supply, ConcurrentSupply { - let (mint_ref, _transfer_ref, burn_ref, _mutate_metadata_ref, _) = create_fungible_asset(creator); + let (mint_ref, _transfer_ref, burn_ref, _mutate_metadata_ref, _) = + create_fungible_asset(creator); let fa = mint(&mint_ref, 100); let cash = extract(&mut fa, 80); assert!(fa.amount == 20, 1); @@ -1385,40 +1467,43 @@ module supra_framework::fungible_asset { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 0x10006, location = Self)] - fun test_fungible_asset_mismatch_when_merge(creator: &signer, aaron: &signer) { + fun test_fungible_asset_mismatch_when_merge( + creator: &signer, aaron: &signer + ) { let (_, _, _, _, metadata1) = create_fungible_asset(creator); let (_, _, _, _, metadata2) = create_fungible_asset(aaron); - let base = FungibleAsset { - metadata: metadata1, - amount: 1, - }; - let addon = FungibleAsset { - metadata: metadata2, - amount: 1 - }; + let base = FungibleAsset { metadata: metadata1, amount: 1 }; + let addon = FungibleAsset { metadata: metadata2, amount: 1 }; merge(&mut base, addon); - let FungibleAsset { - metadata: _, - amount: _ - } = base; + let FungibleAsset { metadata: _, amount: _ } = base; } #[test(fx = @supra_framework, creator = @0xcafe)] - fun test_fungible_asset_upgrade(fx: &signer, creator: &signer) acquires Supply, ConcurrentSupply, FungibleStore, ConcurrentFungibleBalance { + fun test_fungible_asset_upgrade( + fx: &signer, creator: &signer + ) acquires Supply, ConcurrentSupply, FungibleStore, ConcurrentFungibleBalance { let supply_feature = features::get_concurrent_fungible_assets_feature(); let balance_feature = features::get_concurrent_fungible_balance_feature(); - let default_balance_feature = features::get_default_to_concurrent_fungible_balance_feature(); + let default_balance_feature = + features::get_default_to_concurrent_fungible_balance_feature(); - features::change_feature_flags_for_testing(fx, vector[], vector[supply_feature, balance_feature, default_balance_feature]); + features::change_feature_flags_for_testing( + fx, + vector[], + vector[supply_feature, balance_feature, default_balance_feature] + ); let (creator_ref, token_object) = create_test_token(creator); - let (mint_ref, transfer_ref, _burn, _mutate_metadata_ref) = init_test_metadata(&creator_ref); + let (mint_ref, transfer_ref, _burn, _mutate_metadata_ref) = + init_test_metadata(&creator_ref); let test_token = object::convert(token_object); assert!(exists(object::object_address(&test_token)), 1); assert!(!exists(object::object_address(&test_token)), 2); let creator_store = create_test_store(creator, test_token); assert!(exists(object::object_address(&creator_store)), 3); - assert!(!exists(object::object_address(&creator_store)), 4); + assert!( + !exists(object::object_address(&creator_store)), 4 + ); let fa = mint(&mint_ref, 30); assert!(supply(test_token) == option::some(30), 5); @@ -1426,9 +1511,15 @@ module supra_framework::fungible_asset { deposit_with_ref(&transfer_ref, creator_store, fa); assert!(exists(object::object_address(&creator_store)), 13); assert!(borrow_store_resource(&creator_store).balance == 30, 14); - assert!(!exists(object::object_address(&creator_store)), 15); + assert!( + !exists(object::object_address(&creator_store)), 15 + ); - features::change_feature_flags_for_testing(fx, vector[supply_feature, balance_feature], vector[default_balance_feature]); + features::change_feature_flags_for_testing( + fx, + vector[supply_feature, balance_feature], + vector[default_balance_feature] + ); let extend_ref = object::generate_extend_ref(&creator_ref); // manual conversion of supply @@ -1442,28 +1533,47 @@ module supra_framework::fungible_asset { // both store and new balance need to exist. Old balance should be 0. assert!(exists(object::object_address(&creator_store)), 9); assert!(borrow_store_resource(&creator_store).balance == 0, 10); - assert!(exists(object::object_address(&creator_store)), 11); - assert!(aggregator_v2::read(&borrow_global(object::object_address(&creator_store)).balance) == 10, 12); + assert!( + exists(object::object_address(&creator_store)), 11 + ); + assert!( + aggregator_v2::read( + &borrow_global( + object::object_address(&creator_store) + ).balance + ) == 10, + 12 + ); deposit_with_ref(&transfer_ref, creator_store, fb); } #[test(fx = @supra_framework, creator = @0xcafe)] - fun test_fungible_asset_default_concurrent(fx: &signer, creator: &signer) acquires Supply, ConcurrentSupply, FungibleStore, ConcurrentFungibleBalance { + fun test_fungible_asset_default_concurrent( + fx: &signer, creator: &signer + ) acquires Supply, ConcurrentSupply, FungibleStore, ConcurrentFungibleBalance { let supply_feature = features::get_concurrent_fungible_assets_feature(); let balance_feature = features::get_concurrent_fungible_balance_feature(); - let default_balance_feature = features::get_default_to_concurrent_fungible_balance_feature(); + let default_balance_feature = + features::get_default_to_concurrent_fungible_balance_feature(); - features::change_feature_flags_for_testing(fx, vector[supply_feature, balance_feature, default_balance_feature], vector[]); + features::change_feature_flags_for_testing( + fx, + vector[supply_feature, balance_feature, default_balance_feature], + vector[] + ); let (creator_ref, token_object) = create_test_token(creator); - let (mint_ref, transfer_ref, _burn, _mutate_metadata_ref) = init_test_metadata(&creator_ref); + let (mint_ref, transfer_ref, _burn, _mutate_metadata_ref) = + init_test_metadata(&creator_ref); let test_token = object::convert(token_object); assert!(!exists(object::object_address(&test_token)), 1); assert!(exists(object::object_address(&test_token)), 2); let creator_store = create_test_store(creator, test_token); assert!(exists(object::object_address(&creator_store)), 3); - assert!(exists(object::object_address(&creator_store)), 4); + assert!( + exists(object::object_address(&creator_store)), 4 + ); let fa = mint(&mint_ref, 30); assert!(supply(test_token) == option::some(30), 5); @@ -1472,8 +1582,17 @@ module supra_framework::fungible_asset { assert!(exists(object::object_address(&creator_store)), 9); assert!(borrow_store_resource(&creator_store).balance == 0, 10); - assert!(exists(object::object_address(&creator_store)), 11); - assert!(aggregator_v2::read(&borrow_global(object::object_address(&creator_store)).balance) == 30, 12); + assert!( + exists(object::object_address(&creator_store)), 11 + ); + assert!( + aggregator_v2::read( + &borrow_global( + object::object_address(&creator_store) + ).balance + ) == 30, + 12 + ); } #[deprecated] @@ -1481,21 +1600,21 @@ module supra_framework::fungible_asset { struct FungibleAssetEvents has key { deposit_events: event::EventHandle, withdraw_events: event::EventHandle, - frozen_events: event::EventHandle, + frozen_events: event::EventHandle } #[deprecated] struct DepositEvent has drop, store { - amount: u64, + amount: u64 } #[deprecated] struct WithdrawEvent has drop, store { - amount: u64, + amount: u64 } #[deprecated] struct FrozenEvent has drop, store { - frozen: bool, + frozen: bool } -} \ No newline at end of file +} diff --git a/aptos-move/framework/supra-framework/sources/fungible_asset.spec.move b/aptos-move/framework/supra-framework/sources/fungible_asset.spec.move index ed299e76e157b..bb1a38aa37ab6 100644 --- a/aptos-move/framework/supra-framework/sources/fungible_asset.spec.move +++ b/aptos-move/framework/supra-framework/sources/fungible_asset.spec.move @@ -135,6 +135,6 @@ spec supra_framework::fungible_asset { /// spec module { // TODO: verification disabled until this module is specified. - pragma verify=false; + pragma verify = false; } } diff --git a/aptos-move/framework/supra-framework/sources/genesis.move b/aptos-move/framework/supra-framework/sources/genesis.move index 0b42c26955e93..1b346da6a1471 100644 --- a/aptos-move/framework/supra-framework/sources/genesis.move +++ b/aptos-move/framework/supra-framework/sources/genesis.move @@ -34,50 +34,48 @@ module supra_framework::genesis { use supra_framework::transaction_validation; use supra_framework::version; use supra_framework::vesting; - use supra_framework::vesting_without_staking; + use supra_framework::vesting_without_staking; + const VESTING_CONTRACT_SEED: vector = b"VESTING_WIHOUT_STAKING_SEED"; - const VESTING_CONTRACT_SEED: vector = b"VESTING_WIHOUT_STAKING_SEED"; - - const EDUPLICATE_ACCOUNT: u64 = 1; + const EDUPLICATE_ACCOUNT: u64 = 1; const EACCOUNT_DOES_NOT_EXIST: u64 = 2; - const EVESTING_SCHEDULE_IS_ZERO: u64 = 3; - const ENUMERATOR_IS_ZERO: u64 = 4; - const ENO_SHAREHOLDERS: u64 = 5; - const EPERCENTAGE_INVALID: u64 = 6; - const ENUMERATOR_GREATER_THAN_DENOMINATOR: u64 = 7; - const EDENOMINATOR_IS_ZERO: u64 = 8; - const EACCOUNT_NOT_REGISTERED_FOR_COIN: u64 = 9; - + const EVESTING_SCHEDULE_IS_ZERO: u64 = 3; + const ENUMERATOR_IS_ZERO: u64 = 4; + const ENO_SHAREHOLDERS: u64 = 5; + const EPERCENTAGE_INVALID: u64 = 6; + const ENUMERATOR_GREATER_THAN_DENOMINATOR: u64 = 7; + const EDENOMINATOR_IS_ZERO: u64 = 8; + const EACCOUNT_NOT_REGISTERED_FOR_COIN: u64 = 9; struct AccountMap has drop { account_address: address, - balance: u64, + balance: u64 } - struct VestingPoolsMap has copy, drop { - // Address of the admin of the vesting pool - admin_address: address, - // Percentage of account balance should be put in vesting pool - vpool_locking_percentage : u8, - vesting_numerators : vector, - vesting_denominator : u64, - // Withdrawal address for the pool - withdrawal_address: address, - // Shareholders in the vesting pool - shareholders : vector
, - // Cliff duration in seconds - cliff_period_in_seconds: u64, - // Each vesting period duration in seconds - period_duration_in_seconds: u64, - } + struct VestingPoolsMap has copy, drop { + // Address of the admin of the vesting pool + admin_address: address, + // Percentage of account balance should be put in vesting pool + vpool_locking_percentage: u8, + vesting_numerators: vector, + vesting_denominator: u64, + // Withdrawal address for the pool + withdrawal_address: address, + // Shareholders in the vesting pool + shareholders: vector
, + // Cliff duration in seconds + cliff_period_in_seconds: u64, + // Each vesting period duration in seconds + period_duration_in_seconds: u64 + } struct EmployeeAccountMap has copy, drop { accounts: vector
, validator: ValidatorConfigurationWithCommission, vesting_schedule_numerator: vector, vesting_schedule_denominator: u64, - beneficiary_resetter: address, + beneficiary_resetter: address } struct ValidatorConfiguration has copy, drop { @@ -87,13 +85,13 @@ module supra_framework::genesis { stake_amount: u64, consensus_pubkey: vector, network_addresses: vector, - full_node_network_addresses: vector, + full_node_network_addresses: vector } struct ValidatorConfigurationWithCommission has copy, drop { validator_config: ValidatorConfiguration, commission_percentage: u64, - join_during_genesis: bool, + join_during_genesis: bool } struct DelegatorConfiguration has copy, drop { @@ -101,7 +99,7 @@ module supra_framework::genesis { delegation_pool_creation_seed: vector, validator: ValidatorConfigurationWithCommission, delegator_addresses: vector
, - delegator_stakes: vector, + delegator_stakes: vector } struct PboDelegatorConfiguration has copy, drop { @@ -115,7 +113,7 @@ module supra_framework::genesis { //Time from `timestamp::now_seconds()` to start unlocking schedule unlock_startup_time_from_now: u64, //Time for each unlock - unlock_period_duration: u64, + unlock_period_duration: u64 } /// Genesis step 1: Initialize aptos framework account and core modules on chain. @@ -134,12 +132,13 @@ module supra_framework::genesis { rewards_rate: u64, rewards_rate_denominator: u64, voting_power_increase_limit: u64, - genesis_timestamp_in_microseconds: u64, + genesis_timestamp_in_microseconds: u64 ) { // Initialize the aptos framework account. This is the account where system resources and modules will be // deployed to. This will be entirely managed by on-chain governance and no entities have the key or privileges // to use this account. - let (supra_framework_account, supra_framework_signer_cap) = account::create_framework_reserved_account(@supra_framework); + let (supra_framework_account, supra_framework_signer_cap) = + account::create_framework_reserved_account(@supra_framework); // Initialize account configs on aptos framework account. account::initialize(&supra_framework_account); @@ -148,18 +147,23 @@ module supra_framework::genesis { b"script_prologue", b"module_prologue", b"multi_agent_script_prologue", - b"epilogue", + b"epilogue" ); // Give the decentralized on-chain governance control over the core framework account. - supra_governance::store_signer_cap(&supra_framework_account, @supra_framework, supra_framework_signer_cap); + supra_governance::store_signer_cap( + &supra_framework_account, @supra_framework, supra_framework_signer_cap + ); // put reserved framework reserved accounts under aptos governance let framework_reserved_addresses = vector
[@0x2, @0x3, @0x4, @0x5, @0x6, @0x7, @0x8, @0x9, @0xa]; while (!vector::is_empty(&framework_reserved_addresses)) { let address = vector::pop_back
(&mut framework_reserved_addresses); - let (_, framework_signer_cap) = account::create_framework_reserved_account(address); - supra_governance::store_signer_cap(&supra_framework_account, address, framework_signer_cap); + let (_, framework_signer_cap) = + account::create_framework_reserved_account(address); + supra_governance::store_signer_cap( + &supra_framework_account, address, framework_signer_cap + ); }; consensus_config::initialize(&supra_framework_account, consensus_config); @@ -175,7 +179,7 @@ module supra_framework::genesis { allow_validator_set_change, rewards_rate, rewards_rate_denominator, - voting_power_increase_limit, + voting_power_increase_limit ); storage_gas::initialize(&supra_framework_account); gas_schedule::initialize(&supra_framework_account, gas_schedule); @@ -188,7 +192,9 @@ module supra_framework::genesis { reconfiguration::initialize(&supra_framework_account); block::initialize(&supra_framework_account, epoch_interval_microsecs); state_storage::initialize(&supra_framework_account); - timestamp::set_time_has_started(&supra_framework_account, genesis_timestamp_in_microseconds); + timestamp::set_time_has_started( + &supra_framework_account, genesis_timestamp_in_microseconds + ); } /// Genesis step 2: Initialize Supra coin. @@ -206,8 +212,7 @@ module supra_framework::genesis { /// Only called for testnets and e2e tests. fun initialize_core_resources_and_supra_coin( - supra_framework: &signer, - core_resources_auth_key: vector, + supra_framework: &signer, core_resources_auth_key: vector ) { let (burn_cap, mint_cap) = supra_coin::initialize(supra_framework); coin::create_coin_conversion_map(supra_framework); @@ -221,31 +226,42 @@ module supra_framework::genesis { let core_resources = account::create_account(@core_resources); supra_account::register_supra(&core_resources); // register Supra store - account::rotate_authentication_key_internal(&core_resources, core_resources_auth_key); - supra_coin::configure_accounts_for_test(supra_framework, &core_resources, mint_cap); + account::rotate_authentication_key_internal( + &core_resources, core_resources_auth_key + ); + supra_coin::configure_accounts_for_test( + supra_framework, &core_resources, mint_cap + ); } - fun create_accounts(supra_framework: &signer, accounts: vector) { + fun create_accounts( + supra_framework: &signer, accounts: vector + ) { let unique_accounts = vector::empty(); - vector::for_each_ref(&accounts, |account_map| { - let account_map: &AccountMap = account_map; - assert!( - !vector::contains(&unique_accounts, &account_map.account_address), - error::already_exists(EDUPLICATE_ACCOUNT), - ); - vector::push_back(&mut unique_accounts, account_map.account_address); + vector::for_each_ref( + &accounts, + |account_map| { + let account_map: &AccountMap = account_map; + assert!( + !vector::contains(&unique_accounts, &account_map.account_address), + error::already_exists(EDUPLICATE_ACCOUNT) + ); + vector::push_back(&mut unique_accounts, account_map.account_address); - create_account( - supra_framework, - account_map.account_address, - account_map.balance, - ); - }); + create_account( + supra_framework, + account_map.account_address, + account_map.balance + ); + } + ); } /// This creates an funds an account if it doesn't exist. /// If it exists, it just returns the signer. - fun create_account(supra_framework: &signer, account_address: address, balance: u64): signer { + fun create_account( + supra_framework: &signer, account_address: address, balance: u64 + ): signer { if (account::exists_at(account_address)) { create_signer(account_address) } else { @@ -255,25 +271,33 @@ module supra_framework::genesis { account } } - fun create_multiple_multisig_accounts_with_schema( supra_framework: &signer, owner: address, additional_owners: vector
, - num_signatures_required:u64, - metadata_keys:vector, - metadata_values:vector>, - timeout_duration:u64, - balance:u64, + num_signatures_required: u64, + metadata_keys: vector, + metadata_values: vector>, + timeout_duration: u64, + balance: u64, num_of_accounts: u32 ): vector
{ let counter = 0; let result = vector::empty(); while (counter < num_of_accounts) { - let account_addr = create_multisig_account_with_balance(supra_framework, owner, additional_owners, - num_signatures_required,metadata_keys,metadata_values,timeout_duration,balance); - vector::push_back(&mut result,account_addr); + let account_addr = + create_multisig_account_with_balance( + supra_framework, + owner, + additional_owners, + num_signatures_required, + metadata_keys, + metadata_values, + timeout_duration, + balance + ); + vector::push_back(&mut result, account_addr); counter = counter + 1; }; result @@ -283,18 +307,30 @@ module supra_framework::genesis { supra_framework: &signer, owner: address, additional_owners: vector
, - num_signatures_required:u64, + num_signatures_required: u64, metadata_keys: vector, metadata_values: vector>, timeout_duration: u64, - balance:u64, + balance: u64 ): address { - assert!(account::exists_at(owner),error::invalid_argument(EACCOUNT_DOES_NOT_EXIST)); - assert!(vector::all(&additional_owners,|ao_addr|{account::exists_at(*ao_addr)}),error::invalid_argument(EACCOUNT_DOES_NOT_EXIST)); + assert!( + account::exists_at(owner), error::invalid_argument(EACCOUNT_DOES_NOT_EXIST) + ); + assert!( + vector::all(&additional_owners, |ao_addr| { account::exists_at(*ao_addr) }), + error::invalid_argument(EACCOUNT_DOES_NOT_EXIST) + ); let addr = multisig_account::get_next_multisig_account_address(owner); let owner_signer = create_signer(owner); - multisig_account::create_with_owners(&owner_signer,additional_owners,num_signatures_required,metadata_keys,metadata_values,timeout_duration); - supra_coin::mint(supra_framework,addr,balance); + multisig_account::create_with_owners( + &owner_signer, + additional_owners, + num_signatures_required, + metadata_keys, + metadata_values, + timeout_duration + ); + supra_coin::mint(supra_framework, addr, balance); account::increment_sequence_number(owner); addr } @@ -302,104 +338,123 @@ module supra_framework::genesis { fun create_employee_validators( employee_vesting_start: u64, employee_vesting_period_duration: u64, - employees: vector, + employees: vector ) { let unique_accounts = vector::empty(); - vector::for_each_ref(&employees, |employee_group| { - let j = 0; - let employee_group: &EmployeeAccountMap = employee_group; - let num_employees_in_group = vector::length(&employee_group.accounts); - - let buy_ins = simple_map::create(); - - while (j < num_employees_in_group) { - let account = vector::borrow(&employee_group.accounts, j); + vector::for_each_ref( + &employees, + |employee_group| { + let j = 0; + let employee_group: &EmployeeAccountMap = employee_group; + let num_employees_in_group = vector::length(&employee_group.accounts); + + let buy_ins = simple_map::create(); + + while (j < num_employees_in_group) { + let account = vector::borrow(&employee_group.accounts, j); + assert!( + !vector::contains(&unique_accounts, account), + error::already_exists(EDUPLICATE_ACCOUNT) + ); + vector::push_back(&mut unique_accounts, *account); + + let employee = create_signer(*account); + let total = coin::balance(*account); + let coins = coin::withdraw(&employee, total); + simple_map::add(&mut buy_ins, *account, coins); + + j = j + 1; + }; + + let j = 0; + let num_vesting_events = vector::length( + &employee_group.vesting_schedule_numerator + ); + let schedule = vector::empty(); + + while (j < num_vesting_events) { + let numerator = vector::borrow( + &employee_group.vesting_schedule_numerator, j + ); + let event = + fixed_point32::create_from_rational( + *numerator, employee_group.vesting_schedule_denominator + ); + vector::push_back(&mut schedule, event); + + j = j + 1; + }; + + let vesting_schedule = + vesting::create_vesting_schedule( + schedule, + employee_vesting_start, + employee_vesting_period_duration + ); + + let admin = employee_group.validator.validator_config.owner_address; + let admin_signer = &create_signer(admin); + let contract_address = + vesting::create_vesting_contract( + admin_signer, + &employee_group.accounts, + buy_ins, + vesting_schedule, + admin, + employee_group.validator.validator_config.operator_address, + employee_group.validator.validator_config.voter_address, + employee_group.validator.commission_percentage, + x"" + ); + let pool_address = vesting::stake_pool_address(contract_address); + + if (employee_group.beneficiary_resetter != @0x0) { + vesting::set_beneficiary_resetter( + admin_signer, contract_address, employee_group.beneficiary_resetter + ); + }; + + let validator = &employee_group.validator.validator_config; assert!( - !vector::contains(&unique_accounts, account), - error::already_exists(EDUPLICATE_ACCOUNT), + account::exists_at(validator.owner_address), + error::not_found(EACCOUNT_DOES_NOT_EXIST) ); - vector::push_back(&mut unique_accounts, *account); - - let employee = create_signer(*account); - let total = coin::balance(*account); - let coins = coin::withdraw(&employee, total); - simple_map::add(&mut buy_ins, *account, coins); - - j = j + 1; - }; - - let j = 0; - let num_vesting_events = vector::length(&employee_group.vesting_schedule_numerator); - let schedule = vector::empty(); - - while (j < num_vesting_events) { - let numerator = vector::borrow(&employee_group.vesting_schedule_numerator, j); - let event = fixed_point32::create_from_rational(*numerator, employee_group.vesting_schedule_denominator); - vector::push_back(&mut schedule, event); - - j = j + 1; - }; - - let vesting_schedule = vesting::create_vesting_schedule( - schedule, - employee_vesting_start, - employee_vesting_period_duration, - ); - - let admin = employee_group.validator.validator_config.owner_address; - let admin_signer = &create_signer(admin); - let contract_address = vesting::create_vesting_contract( - admin_signer, - &employee_group.accounts, - buy_ins, - vesting_schedule, - admin, - employee_group.validator.validator_config.operator_address, - employee_group.validator.validator_config.voter_address, - employee_group.validator.commission_percentage, - x"", - ); - let pool_address = vesting::stake_pool_address(contract_address); - - if (employee_group.beneficiary_resetter != @0x0) { - vesting::set_beneficiary_resetter(admin_signer, contract_address, employee_group.beneficiary_resetter); - }; - - let validator = &employee_group.validator.validator_config; - assert!( - account::exists_at(validator.owner_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), - ); - assert!( - account::exists_at(validator.operator_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), - ); - assert!( - account::exists_at(validator.voter_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), - ); - if (employee_group.validator.join_during_genesis) { - initialize_validator(pool_address, validator); - }; - }); + assert!( + account::exists_at(validator.operator_address), + error::not_found(EACCOUNT_DOES_NOT_EXIST) + ); + assert!( + account::exists_at(validator.voter_address), + error::not_found(EACCOUNT_DOES_NOT_EXIST) + ); + if (employee_group.validator.join_during_genesis) { + initialize_validator(pool_address, validator); + }; + } + ); } /// DEPRECATED - /// + /// fun create_initialize_validators_with_commission( supra_framework: &signer, use_staking_contract: bool, - validators: vector, + validators: vector ) { - vector::for_each_ref(&validators, |validator| { - let validator: &ValidatorConfigurationWithCommission = validator; - create_initialize_validator(supra_framework, validator, use_staking_contract); - }); + vector::for_each_ref( + &validators, + |validator| { + let validator: &ValidatorConfigurationWithCommission = validator; + create_initialize_validator( + supra_framework, validator, use_staking_contract + ); + } + ); } /// DEPRECATED - /// + /// /// Sets up the initial validator set for the network. /// The validator "owner" accounts, and their authentication /// Addresses (and keys) are encoded in the `owners` @@ -410,51 +465,66 @@ module supra_framework::genesis { /// /// Network address fields are a vector per account, where each entry is a vector of addresses /// encoded in a single BCS byte array. - fun create_initialize_validators(supra_framework: &signer, validators: vector) { + fun create_initialize_validators( + supra_framework: &signer, validators: vector + ) { let validators_with_commission = vector::empty(); - vector::for_each_reverse(validators, |validator| { - let validator_with_commission = ValidatorConfigurationWithCommission { - validator_config: validator, - commission_percentage: 0, - join_during_genesis: true, - }; - vector::push_back(&mut validators_with_commission, validator_with_commission); - }); + vector::for_each_reverse( + validators, + |validator| { + let validator_with_commission = ValidatorConfigurationWithCommission { + validator_config: validator, + commission_percentage: 0, + join_during_genesis: true + }; + vector::push_back( + &mut validators_with_commission, validator_with_commission + ); + } + ); - create_initialize_validators_with_commission(supra_framework, false, validators_with_commission); + create_initialize_validators_with_commission( + supra_framework, false, validators_with_commission + ); } fun create_initialize_validator( supra_framework: &signer, commission_config: &ValidatorConfigurationWithCommission, - use_staking_contract: bool, + use_staking_contract: bool ) { let validator = &commission_config.validator_config; - let owner = &create_account(supra_framework, validator.owner_address, validator.stake_amount); + let owner = + &create_account( + supra_framework, validator.owner_address, validator.stake_amount + ); create_account(supra_framework, validator.operator_address, 0); create_account(supra_framework, validator.voter_address, 0); // Initialize the stake pool and join the validator set. - let pool_address = if (use_staking_contract) { - staking_contract::create_staking_contract( - owner, - validator.operator_address, - validator.voter_address, - validator.stake_amount, - commission_config.commission_percentage, - x"", - ); - staking_contract::stake_pool_address(validator.owner_address, validator.operator_address) - } else { - stake::initialize_stake_owner( - owner, - validator.stake_amount, - validator.operator_address, - validator.voter_address, - ); - validator.owner_address - }; + let pool_address = + if (use_staking_contract) { + staking_contract::create_staking_contract( + owner, + validator.operator_address, + validator.voter_address, + validator.stake_amount, + commission_config.commission_percentage, + x"" + ); + staking_contract::stake_pool_address( + validator.owner_address, validator.operator_address + ) + } else { + stake::initialize_stake_owner( + owner, + validator.stake_amount, + validator.operator_address, + validator.voter_address + ); + validator.owner_address + }; if (commission_config.join_during_genesis) { initialize_validator(pool_address, validator); @@ -463,44 +533,69 @@ module supra_framework::genesis { fun create_pbo_delegation_pools( pbo_delegator_configs: vector, - delegation_percentage: u64, + delegation_percentage: u64 ) { - let unique_accounts: vector
= vector::empty(); - assert!(delegation_percentage > 0 && delegation_percentage <= 100, error::invalid_argument(EPERCENTAGE_INVALID)); - vector::for_each_ref(&pbo_delegator_configs, |pbo_delegator_config| { - let pbo_delegator_config: &PboDelegatorConfiguration = pbo_delegator_config; - assert!(!vector::contains(&unique_accounts,&pbo_delegator_config.delegator_config.owner_address), - error::invalid_argument(EDUPLICATE_ACCOUNT)); - vector::push_back(&mut unique_accounts,pbo_delegator_config.delegator_config.owner_address); - create_pbo_delegation_pool(pbo_delegator_config, delegation_percentage); - }); + let unique_accounts: vector
= vector::empty(); + assert!( + delegation_percentage > 0 && delegation_percentage <= 100, + error::invalid_argument(EPERCENTAGE_INVALID) + ); + vector::for_each_ref( + &pbo_delegator_configs, + |pbo_delegator_config| { + let pbo_delegator_config: &PboDelegatorConfiguration = + pbo_delegator_config; + assert!( + !vector::contains( + &unique_accounts, + &pbo_delegator_config.delegator_config.owner_address + ), + error::invalid_argument(EDUPLICATE_ACCOUNT) + ); + vector::push_back( + &mut unique_accounts, + pbo_delegator_config.delegator_config.owner_address + ); + create_pbo_delegation_pool(pbo_delegator_config, delegation_percentage); + } + ); } fun create_pbo_delegation_pool( - pbo_delegator_config: &PboDelegatorConfiguration, - delegation_percentage: u64, + pbo_delegator_config: &PboDelegatorConfiguration, delegation_percentage: u64 ) { - assert!(delegation_percentage>0 && delegation_percentage<=100,error::invalid_argument(EPERCENTAGE_INVALID)); - let unique_accounts:vector
= vector::empty(); - vector::for_each_ref(&pbo_delegator_config.delegator_config.delegator_addresses, |delegator_address| { - let delegator_address: &address = delegator_address; - assert!( - !vector::contains(&unique_accounts, delegator_address), - error::already_exists(EDUPLICATE_ACCOUNT), - ); - vector::push_back(&mut unique_accounts, *delegator_address); - }); - let owner_signer = create_signer(pbo_delegator_config.delegator_config.owner_address); + assert!( + delegation_percentage > 0 && delegation_percentage <= 100, + error::invalid_argument(EPERCENTAGE_INVALID) + ); + let unique_accounts: vector
= vector::empty(); + vector::for_each_ref( + &pbo_delegator_config.delegator_config.delegator_addresses, + |delegator_address| { + let delegator_address: &address = delegator_address; + assert!( + !vector::contains(&unique_accounts, delegator_address), + error::already_exists(EDUPLICATE_ACCOUNT) + ); + vector::push_back(&mut unique_accounts, *delegator_address); + } + ); + let owner_signer = + create_signer(pbo_delegator_config.delegator_config.owner_address); // get a list of delegator addresses, withdraw the coin from them and merge them into a single account - let delegator_addresses = pbo_delegator_config.delegator_config.delegator_addresses; + let delegator_addresses = + pbo_delegator_config.delegator_config.delegator_addresses; let coinInitialization = coin::zero(); - vector::for_each(delegator_addresses, |delegator_address| { - let delegator = &create_signer(delegator_address); - let total = coin::balance(delegator_address); - let withdraw_amount = total * delegation_percentage / 100; - let coins = coin::withdraw(delegator, withdraw_amount); - coin::merge(&mut coinInitialization, coins); - }); + vector::for_each( + delegator_addresses, + |delegator_address| { + let delegator = &create_signer(delegator_address); + let total = coin::balance(delegator_address); + let withdraw_amount = total * delegation_percentage / 100; + let coins = coin::withdraw(delegator, withdraw_amount); + coin::merge(&mut coinInitialization, coins); + } + ); pbo_delegation_pool::initialize_delegation_pool( &owner_signer, option::some(pbo_delegator_config.multisig_admin), @@ -511,112 +606,148 @@ module supra_framework::genesis { coinInitialization, pbo_delegator_config.unlock_schedule_numerators, pbo_delegator_config.unlock_schedule_denominator, - pbo_delegator_config.unlock_startup_time_from_now+timestamp::now_seconds(), - pbo_delegator_config.unlock_period_duration, + pbo_delegator_config.unlock_startup_time_from_now + + timestamp::now_seconds(), + pbo_delegator_config.unlock_period_duration ); - let pool_address = pbo_delegation_pool::get_owned_pool_address(pbo_delegator_config.delegator_config.owner_address); - let validator = pbo_delegator_config.delegator_config.validator.validator_config; - pbo_delegation_pool::set_operator(&owner_signer,validator.operator_address); - pbo_delegation_pool::set_delegated_voter(&owner_signer,validator.voter_address); - assert_validator_addresses_check(&validator); + let pool_address = + pbo_delegation_pool::get_owned_pool_address( + pbo_delegator_config.delegator_config.owner_address + ); + let validator = pbo_delegator_config.delegator_config.validator.validator_config; + pbo_delegation_pool::set_operator(&owner_signer, validator.operator_address); + pbo_delegation_pool::set_delegated_voter(&owner_signer, validator.voter_address); + assert_validator_addresses_check(&validator); - if (pbo_delegator_config.delegator_config.validator.join_during_genesis) { - initialize_validator(pool_address,&validator); + if (pbo_delegator_config.delegator_config.validator.join_during_genesis) { + initialize_validator(pool_address, &validator); }; } - fun assert_validator_addresses_check(validator: &ValidatorConfiguration) { + fun assert_validator_addresses_check( + validator: &ValidatorConfiguration + ) { assert!( account::exists_at(validator.owner_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), + error::not_found(EACCOUNT_DOES_NOT_EXIST) ); assert!( account::exists_at(validator.operator_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), + error::not_found(EACCOUNT_DOES_NOT_EXIST) ); assert!( account::exists_at(validator.voter_address), - error::not_found(EACCOUNT_DOES_NOT_EXIST), + error::not_found(EACCOUNT_DOES_NOT_EXIST) ); - } + } fun create_vesting_without_staking_pools( - vesting_pool_map : vector + vesting_pool_map: vector ) { let unique_accounts: vector
= vector::empty(); - vector::for_each_ref(&vesting_pool_map, |pool_config|{ - let pool_config: &VestingPoolsMap = pool_config; - let schedule = vector::empty(); - let schedule_length = vector::length(&pool_config.vesting_numerators); - assert!(schedule_length > 0, error::invalid_argument(EVESTING_SCHEDULE_IS_ZERO)); - assert!(pool_config.vesting_denominator > 0, error::invalid_argument(EDENOMINATOR_IS_ZERO)); - assert!(pool_config.vpool_locking_percentage > 0 && pool_config.vpool_locking_percentage <=100 , - error::invalid_argument(EPERCENTAGE_INVALID)); - //check the sum of numerator are <= denominator. - let sum = vector::fold(pool_config.vesting_numerators,0,|acc, x| acc + x); - // Check that total of all fraction in `vesting_schedule` is not greater than 1 - assert!(sum <= pool_config.vesting_denominator, - error::invalid_argument(ENUMERATOR_GREATER_THAN_DENOMINATOR)); - //assert that withdrawal_address is registered to receive SupraCoin - assert!(coin::is_account_registered(pool_config.withdrawal_address), error::invalid_argument(EACCOUNT_NOT_REGISTERED_FOR_COIN)); - //assertion on admin_address? - let admin = create_signer(pool_config.admin_address); - - //Create the vesting schedule - let j=0; - while (j < schedule_length) { - let numerator = *vector::borrow(&pool_config.vesting_numerators,j); - assert!(numerator > 0, error::invalid_argument(ENUMERATOR_IS_ZERO)); - let event = fixed_point32::create_from_rational(numerator,pool_config.vesting_denominator); - vector::push_back(&mut schedule,event); - j = j + 1; - }; - - let vesting_schedule = vesting_without_staking::create_vesting_schedule( - schedule, - timestamp::now_seconds() + pool_config.cliff_period_in_seconds, - pool_config.period_duration_in_seconds, - ); - - let buy_ins = simple_map::create(); - let num_shareholders = vector::length(&pool_config.shareholders); - assert!(num_shareholders > 0, error::invalid_argument(ENO_SHAREHOLDERS)); - let j = 0; - while (j < num_shareholders) { - let shareholder = *vector::borrow(&pool_config.shareholders,j); - assert!(!vector::contains(&unique_accounts,&shareholder), error::already_exists(EDUPLICATE_ACCOUNT)); - vector::push_back(&mut unique_accounts,shareholder); - let shareholder_signer = create_signer(shareholder); - let amount = coin::balance(shareholder); - let amount_to_extract = (amount * (pool_config.vpool_locking_percentage as u64)) / 100; - let coin_share = coin::withdraw(&shareholder_signer, amount_to_extract); - simple_map::add(&mut buy_ins,shareholder,coin_share); - j = j + 1; - }; - vesting_without_staking::create_vesting_contract( - &admin, - buy_ins, - vesting_schedule, - pool_config.withdrawal_address, - VESTING_CONTRACT_SEED - ); - }); + vector::for_each_ref( + &vesting_pool_map, + |pool_config| { + let pool_config: &VestingPoolsMap = pool_config; + let schedule = vector::empty(); + let schedule_length = vector::length(&pool_config.vesting_numerators); + assert!( + schedule_length > 0, error::invalid_argument( + EVESTING_SCHEDULE_IS_ZERO + ) + ); + assert!( + pool_config.vesting_denominator > 0, + error::invalid_argument(EDENOMINATOR_IS_ZERO) + ); + assert!( + pool_config.vpool_locking_percentage > 0 + && pool_config.vpool_locking_percentage <= 100, + error::invalid_argument(EPERCENTAGE_INVALID) + ); + //check the sum of numerator are <= denominator. + let sum = vector::fold(pool_config.vesting_numerators, 0, |acc, x| acc + + x); + // Check that total of all fraction in `vesting_schedule` is not greater than 1 + assert!( + sum <= pool_config.vesting_denominator, + error::invalid_argument(ENUMERATOR_GREATER_THAN_DENOMINATOR) + ); + //assert that withdrawal_address is registered to receive SupraCoin + assert!( + coin::is_account_registered(pool_config.withdrawal_address), + error::invalid_argument(EACCOUNT_NOT_REGISTERED_FOR_COIN) + ); + //assertion on admin_address? + let admin = create_signer(pool_config.admin_address); + + //Create the vesting schedule + let j = 0; + while (j < schedule_length) { + let numerator = *vector::borrow(&pool_config.vesting_numerators, j); + assert!(numerator > 0, error::invalid_argument(ENUMERATOR_IS_ZERO)); + let event = + fixed_point32::create_from_rational( + numerator, pool_config.vesting_denominator + ); + vector::push_back(&mut schedule, event); + j = j + 1; + }; + + let vesting_schedule = + vesting_without_staking::create_vesting_schedule( + schedule, + timestamp::now_seconds() + pool_config.cliff_period_in_seconds, + pool_config.period_duration_in_seconds + ); + + let buy_ins = simple_map::create(); + let num_shareholders = vector::length(&pool_config.shareholders); + assert!(num_shareholders > 0, error::invalid_argument(ENO_SHAREHOLDERS)); + let j = 0; + while (j < num_shareholders) { + let shareholder = *vector::borrow(&pool_config.shareholders, j); + assert!( + !vector::contains(&unique_accounts, &shareholder), + error::already_exists(EDUPLICATE_ACCOUNT) + ); + vector::push_back(&mut unique_accounts, shareholder); + let shareholder_signer = create_signer(shareholder); + let amount = coin::balance(shareholder); + let amount_to_extract = + (amount * (pool_config.vpool_locking_percentage as u64)) / 100; + let coin_share = + coin::withdraw(&shareholder_signer, amount_to_extract); + simple_map::add(&mut buy_ins, shareholder, coin_share); + j = j + 1; + }; + vesting_without_staking::create_vesting_contract( + &admin, + buy_ins, + vesting_schedule, + pool_config.withdrawal_address, + VESTING_CONTRACT_SEED + ); + } + ); } - fun initialize_validator(pool_address: address, validator: &ValidatorConfiguration) { + fun initialize_validator( + pool_address: address, validator: &ValidatorConfiguration + ) { let operator = &create_signer(validator.operator_address); stake::rotate_consensus_key_genesis( operator, pool_address, - validator.consensus_pubkey, + validator.consensus_pubkey ); stake::update_network_and_fullnode_addresses( operator, pool_address, validator.network_addresses, - validator.full_node_network_addresses, + validator.full_node_network_addresses ); stake::join_validator_set_internal(operator, pool_address); } @@ -676,9 +807,11 @@ module supra_framework::genesis { rewards_rate, rewards_rate_denominator, voting_power_increase_limit, - 0, + 0 + ); + features::change_feature_flags_for_verification( + supra_framework, vector[1, 2, 11], vector[] ); - features::change_feature_flags_for_verification(supra_framework, vector[1, 2, 11], vector[]); initialize_supra_coin(supra_framework); supra_governance::initialize_for_verification( supra_framework, @@ -686,10 +819,12 @@ module supra_framework::genesis { // required_proposer_stake, voting_duration_secs, supra_min_voting_threshold, - voters, + voters ); create_accounts(supra_framework, accounts); - create_employee_validators(employee_vesting_start, employee_vesting_period_duration, employees); + create_employee_validators( + employee_vesting_start, employee_vesting_period_duration, employees + ); create_initialize_validators_with_commission(supra_framework, true, validators); set_genesis_end(supra_framework); } @@ -713,7 +848,7 @@ module supra_framework::genesis { 1, 1, 30, - 0, + 0 ) } @@ -755,14 +890,8 @@ module supra_framework::genesis { let addr1 = @0x121345; let accounts = vector[ - AccountMap { - account_address: addr0, - balance: 12345, - }, - AccountMap { - account_address: addr1, - balance: 67890, - }, + AccountMap { account_address: addr0, balance: 12345 }, + AccountMap { account_address: addr1, balance: 67890 } ]; create_accounts(supra_framework, accounts); @@ -773,14 +902,19 @@ module supra_framework::genesis { assert!(coin::balance(addr0) == 12345, 2); } - #[test_only] - use aptos_std::ed25519; + #[test_only] + use aptos_std::ed25519; #[test_only] - fun generate_multisig_account(owner: &signer, addition_owner: vector
): address { + fun generate_multisig_account( + owner: &signer, addition_owner: vector
+ ): address { let owner_addr = aptos_std::signer::address_of(owner); - let multisig_addr = multisig_account::get_next_multisig_account_address(owner_addr); - multisig_account::create_with_owners(owner, addition_owner, 2, vector[], vector[], 300); + let multisig_addr = + multisig_account::get_next_multisig_account_address(owner_addr); + multisig_account::create_with_owners( + owner, addition_owner, 2, vector[], vector[], 300 + ); multisig_addr } @@ -794,7 +928,9 @@ module supra_framework::genesis { use std::features; let feature = features::get_new_accounts_default_to_fa_supra_store_feature(); - features::change_feature_flags_for_testing(supra_framework, vector[feature], vector[]); + features::change_feature_flags_for_testing( + supra_framework, vector[feature], vector[] + ); aggregator_factory::initialize_aggregator_factory_for_test(supra_framework); let (burn_cap, mint_cap) = supra_coin::initialize(supra_framework); @@ -804,64 +940,78 @@ module supra_framework::genesis { supra_account::register_supra(&core_resources); // registers SUPRA store let apt_metadata = object::address_to_object(@aptos_fungible_asset); - assert!(primary_fungible_store::primary_store_exists(@core_resources, apt_metadata), 2); + assert!( + primary_fungible_store::primary_store_exists(@core_resources, apt_metadata), 2 + ); - supra_coin::configure_accounts_for_test(supra_framework, &core_resources, mint_cap); + supra_coin::configure_accounts_for_test( + supra_framework, &core_resources, mint_cap + ); coin::destroy_burn_cap(burn_cap); coin::destroy_mint_cap(mint_cap); } #[test(supra_framework = @0x1)] fun test_create_pbo_delegation_pool(supra_framework: &signer) { - use std::features; + use std::features; setup(); - features::change_feature_flags_for_testing(supra_framework,vector[11],vector[]); + features::change_feature_flags_for_testing(supra_framework, vector[11], vector[]); initialize_supra_coin(supra_framework); let owner = @0x121341; - let (_, pk_1) = stake::generate_identity(); - let _pk_1 = ed25519::unvalidated_public_key_to_bytes(&pk_1); + let (_, pk_1) = stake::generate_identity(); + let _pk_1 = ed25519::unvalidated_public_key_to_bytes(&pk_1); create_account(supra_framework, owner, 0); - let validator_config_commission = ValidatorConfigurationWithCommission{ - validator_config: ValidatorConfiguration{ + let validator_config_commission = ValidatorConfigurationWithCommission { + validator_config: ValidatorConfiguration { owner_address: @0x121341, operator_address: @0x121342, voter_address: @0x121343, stake_amount: 0, consensus_pubkey: _pk_1, network_addresses: x"222222", - full_node_network_addresses: x"333333", + full_node_network_addresses: x"333333" }, commission_percentage: 10, - join_during_genesis: true, + join_during_genesis: true }; let delegation_pool_creation_seed = x"121341"; let delegator_addresses = vector[@0x121342, @0x121343]; let initial_balance = vector[100 * ONE_SUPRA, 200 * ONE_SUPRA]; let i = 0; let delegation_percentage = 10; - let delegator_stakes : vector = vector::empty(); + let delegator_stakes: vector = vector::empty(); while (i < vector::length(&delegator_addresses)) { - create_account(supra_framework, *vector::borrow(&delegator_addresses, i), *vector::borrow(&initial_balance, i)); - vector::push_back(&mut delegator_stakes, *vector::borrow(&initial_balance, i) * delegation_percentage / 100); + create_account( + supra_framework, + *vector::borrow(&delegator_addresses, i), + *vector::borrow(&initial_balance, i) + ); + vector::push_back( + &mut delegator_stakes, + *vector::borrow(&initial_balance, i) * delegation_percentage / 100 + ); i = i + 1; }; let principle_lockup_time = 100; - let multisig = generate_multisig_account(&account::create_signer_for_test(owner), vector[@0x12134]); + let multisig = + generate_multisig_account( + &account::create_signer_for_test(owner), vector[@0x12134] + ); let pbo_delegator_config = PboDelegatorConfiguration { multisig_admin: multisig, unlock_period_duration: 12, unlock_schedule_denominator: 10, unlock_schedule_numerators: vector[2, 2, 3], unlock_startup_time_from_now: principle_lockup_time, - delegator_config: DelegatorConfiguration{ + delegator_config: DelegatorConfiguration { owner_address: owner, validator: validator_config_commission, delegation_pool_creation_seed, delegator_addresses, - delegator_stakes, - }, + delegator_stakes + } }; create_pbo_delegation_pool(&pbo_delegator_config, delegation_percentage); let pool_address = pbo_delegation_pool::get_owned_pool_address(owner); @@ -870,98 +1020,113 @@ module supra_framework::genesis { #[test(supra_framework = @0x1)] fun test_create_pbo_delegation_pools(supra_framework: &signer) { - use std::features; + use std::features; setup(); - features::change_feature_flags_for_testing(supra_framework,vector[11],vector[]); + features::change_feature_flags_for_testing(supra_framework, vector[11], vector[]); initialize_supra_coin(supra_framework); let owner1 = @0x121341; - create_account(supra_framework,owner1,0); - let (_, pk_1)=stake::generate_identity(); - let (_, pk_2)=stake::generate_identity(); - let _pk_1 = ed25519::unvalidated_public_key_to_bytes(&pk_1); - let _pk_2 = ed25519::unvalidated_public_key_to_bytes(&pk_2); - let validator_config_commission1 = ValidatorConfigurationWithCommission{ - validator_config: ValidatorConfiguration{ + create_account(supra_framework, owner1, 0); + let (_, pk_1) = stake::generate_identity(); + let (_, pk_2) = stake::generate_identity(); + let _pk_1 = ed25519::unvalidated_public_key_to_bytes(&pk_1); + let _pk_2 = ed25519::unvalidated_public_key_to_bytes(&pk_2); + let validator_config_commission1 = ValidatorConfigurationWithCommission { + validator_config: ValidatorConfiguration { owner_address: owner1, operator_address: @0x121342, voter_address: @0x121343, stake_amount: 100 * ONE_SUPRA, consensus_pubkey: _pk_1, network_addresses: x"222222", - full_node_network_addresses: x"333333", + full_node_network_addresses: x"333333" }, commission_percentage: 10, - join_during_genesis: true, + join_during_genesis: true }; let delegation_pool_creation_seed1 = x"121341"; let delegator_address1 = vector[@0x121342, @0x121343]; let initial_balance1 = vector[100 * ONE_SUPRA, 200 * ONE_SUPRA]; - let delegator_stakes1:vector = vector::empty(); + let delegator_stakes1: vector = vector::empty(); let delegation_percentage: u64 = 10; let i = 0; while (i < vector::length(&delegator_address1)) { - create_account(supra_framework, *vector::borrow(&delegator_address1, i), *vector::borrow(&initial_balance1, i)); - vector::push_back(&mut delegator_stakes1, *vector::borrow(&initial_balance1, i) * delegation_percentage / 100); + create_account( + supra_framework, + *vector::borrow(&delegator_address1, i), + *vector::borrow(&initial_balance1, i) + ); + vector::push_back( + &mut delegator_stakes1, + *vector::borrow(&initial_balance1, i) * delegation_percentage / 100 + ); i = i + 1; }; let principle_lockup_time1 = 100; - let multisig1 = generate_multisig_account(&account::create_signer_for_test(owner1), vector[@0x121342]); - let pbo_delegator_config1 = PboDelegatorConfiguration{ + let multisig1 = + generate_multisig_account( + &account::create_signer_for_test(owner1), vector[@0x121342] + ); + let pbo_delegator_config1 = PboDelegatorConfiguration { multisig_admin: multisig1, unlock_period_duration: 12, unlock_schedule_denominator: 10, unlock_schedule_numerators: vector[2, 2, 3], unlock_startup_time_from_now: principle_lockup_time1, - delegator_config: DelegatorConfiguration{ + delegator_config: DelegatorConfiguration { owner_address: owner1, validator: validator_config_commission1, delegation_pool_creation_seed: delegation_pool_creation_seed1, delegator_addresses: delegator_address1, - delegator_stakes: delegator_stakes1, - }, + delegator_stakes: delegator_stakes1 + } }; let owner2 = @0x121344; create_account(supra_framework, owner2, 0); - let validator_config_commission2 = ValidatorConfigurationWithCommission{ - validator_config: ValidatorConfiguration{ + let validator_config_commission2 = ValidatorConfigurationWithCommission { + validator_config: ValidatorConfiguration { owner_address: owner2, operator_address: @0x121345, voter_address: @0x121346, stake_amount: 100 * ONE_SUPRA, consensus_pubkey: _pk_2, network_addresses: x"222222", - full_node_network_addresses: x"333333", + full_node_network_addresses: x"333333" }, commission_percentage: 20, - join_during_genesis: true, + join_during_genesis: true }; let delegation_pool_creation_seed2 = x"121344"; let delegator_address2 = vector[@0x121345, @0x121346]; let initial_balance2 = vector[300 * ONE_SUPRA, 400 * ONE_SUPRA]; let j = 0; - let delegator_stakes2:vector = vector::empty(); + let delegator_stakes2: vector = vector::empty(); while (j < vector::length(&delegator_address2)) { - let bal = vector::borrow(&initial_balance2,j); + let bal = vector::borrow(&initial_balance2, j); create_account(supra_framework, *vector::borrow(&delegator_address2, j), *bal); - vector::push_back(&mut delegator_stakes2, (*bal) * delegation_percentage / 100); + vector::push_back( + &mut delegator_stakes2, (*bal) * delegation_percentage / 100 + ); j = j + 1; }; let principle_lockup_time2 = 200; - let multisig2 = generate_multisig_account(&account::create_signer_for_test(owner2), vector[@0x121347]); - let pbo_delegator_config2 = PboDelegatorConfiguration{ + let multisig2 = + generate_multisig_account( + &account::create_signer_for_test(owner2), vector[@0x121347] + ); + let pbo_delegator_config2 = PboDelegatorConfiguration { multisig_admin: multisig2, unlock_period_duration: 12, unlock_schedule_denominator: 10, unlock_schedule_numerators: vector[2, 2, 3], unlock_startup_time_from_now: principle_lockup_time2, - delegator_config: DelegatorConfiguration{ + delegator_config: DelegatorConfiguration { owner_address: owner2, validator: validator_config_commission2, delegation_pool_creation_seed: delegation_pool_creation_seed2, delegator_addresses: delegator_address2, - delegator_stakes: delegator_stakes2, - }, + delegator_stakes: delegator_stakes2 + } }; let pbo_delegator_configs = vector[pbo_delegator_config1, pbo_delegator_config2]; create_pbo_delegation_pools(pbo_delegator_configs, delegation_percentage); @@ -970,60 +1135,101 @@ module supra_framework::genesis { assert!(pbo_delegation_pool::delegation_pool_exists(pool_address1), 0); assert!(pbo_delegation_pool::delegation_pool_exists(pool_address2), 1); } - - #[test (supra_framework=@0x1, owner1=@0x1234, owner2=@0x2345, owner3=@0x3456)] - fun test_create_multisig_account_with_balance(supra_framework: &signer, owner1: address, owner2: address, owner3: address) - { + + #[test( + supra_framework = @0x1, owner1 = @0x1234, owner2 = @0x2345, owner3 = @0x3456 + )] + fun test_create_multisig_account_with_balance( + supra_framework: &signer, + owner1: address, + owner2: address, + owner3: address + ) { setup(); initialize_supra_coin(supra_framework); let additional_owners = vector[owner2, owner3]; - let timeout_duration=600; + let timeout_duration = 600; let num_signatures_required = 2; - let metadata_keys: vector =vector::empty(); + let metadata_keys: vector = vector::empty(); let metadata_values: vector> = vector::empty(); let balance = 10000000000; - create_account(supra_framework,owner1,0); - create_account(supra_framework,owner2,0); - create_account(supra_framework,owner3,0); - let addr = create_multisig_account_with_balance(supra_framework,owner1, additional_owners, - num_signatures_required, metadata_keys, metadata_values, timeout_duration,balance); + create_account(supra_framework, owner1, 0); + create_account(supra_framework, owner2, 0); + create_account(supra_framework, owner3, 0); + let addr = + create_multisig_account_with_balance( + supra_framework, + owner1, + additional_owners, + num_signatures_required, + metadata_keys, + metadata_values, + timeout_duration, + balance + ); //Ensure it is indeed on-chain multisig account with required threshold - assert!(multisig_account::num_signatures_required(addr)==2,1); + assert!(multisig_account::num_signatures_required(addr) == 2, 1); //Ensure the account is seeded with supplied balance - assert!(coin::balance(addr)==balance,2); + assert!(coin::balance(addr) == balance, 2); // Ensure that you can transfer out funds from multisig account let multisig_signer = create_signer(addr); - coin::transfer(&multisig_signer,owner1,balance); - assert!(coin::balance(owner1)==balance,3); + coin::transfer(&multisig_signer, owner1, balance); + assert!(coin::balance(owner1) == balance, 3); } - #[test (supra_framework=@0x1, owner1=@0x1234, owner2=@0x2345, owner3=@0x3456)] - fun test_create_multisig_account_with_schema(supra_framework: &signer, owner1: address, owner2: address, owner3: address) - { + #[test( + supra_framework = @0x1, owner1 = @0x1234, owner2 = @0x2345, owner3 = @0x3456 + )] + fun test_create_multisig_account_with_schema( + supra_framework: &signer, + owner1: address, + owner2: address, + owner3: address + ) { setup(); initialize_supra_coin(supra_framework); let additional_owners = vector[owner2, owner3]; - let timeout_duration=600; + let timeout_duration = 600; let num_signatures_required = 2; - let metadata_keys: vector =vector::empty(); + let metadata_keys: vector = vector::empty(); let metadata_values: vector> = vector::empty(); let balance = 10000000000; let num_accounts = 3; - create_account(supra_framework,owner1,0); - create_account(supra_framework,owner2,0); - create_account(supra_framework,owner3,0); - let vec_addr = create_multiple_multisig_accounts_with_schema(supra_framework,owner1, - additional_owners,num_signatures_required,metadata_keys,metadata_values, - timeout_duration,balance,num_accounts); + create_account(supra_framework, owner1, 0); + create_account(supra_framework, owner2, 0); + create_account(supra_framework, owner3, 0); + let vec_addr = + create_multiple_multisig_accounts_with_schema( + supra_framework, + owner1, + additional_owners, + num_signatures_required, + metadata_keys, + metadata_values, + timeout_duration, + balance, + num_accounts + ); //Ensure they are indeed on-chain multisig account with required threshold - assert!(vector::all(&vec_addr,|elem| {multisig_account::num_signatures_required(*elem)==2}),1); + assert!( + vector::all( + &vec_addr, |elem| { multisig_account::num_signatures_required(*elem) + == 2 } + ), + 1 + ); //Ensure the accounts are seeded with supplied balance - assert!(vector::all(&vec_addr,|elem| {coin::balance(*elem)==balance}),2); + assert!( + vector::all(&vec_addr, |elem| { + coin::balance(*elem) == balance + }), 2 + ); } - #[test(supra_framework = @0x1)] - fun test_create_vesting_without_staking_pools(supra_framework: &signer) { + fun test_create_vesting_without_staking_pools( + supra_framework: &signer + ) { // use supra_framework::supra_account::create_account; setup(); initialize_supra_coin(supra_framework); @@ -1035,17 +1241,20 @@ module supra_framework::genesis { let vesting_denominator = 6; let withdrawal_address = @0x121342; let shareholders = vector[@0x121343, @0x121344]; - create_account(supra_framework, admin_address , 0); - create_account(supra_framework, withdrawal_address , 0); - vector::for_each_ref(&shareholders, |addr| { - let addr: address = *addr; - if (!account::exists_at(addr)) { - create_account(supra_framework, addr, 100 * ONE_SUPRA); - }; - }); + create_account(supra_framework, admin_address, 0); + create_account(supra_framework, withdrawal_address, 0); + vector::for_each_ref( + &shareholders, + |addr| { + let addr: address = *addr; + if (!account::exists_at(addr)) { + create_account(supra_framework, addr, 100 * ONE_SUPRA); + }; + } + ); let cliff_period_in_seconds = 100; let period_duration_in_seconds = 200; - let pool_config = VestingPoolsMap{ + let pool_config = VestingPoolsMap { admin_address: admin_address, vpool_locking_percentage: vpool_locking_percentage, vesting_numerators: vesting_numerators, @@ -1053,7 +1262,7 @@ module supra_framework::genesis { withdrawal_address: withdrawal_address, shareholders: shareholders, cliff_period_in_seconds: cliff_period_in_seconds, - period_duration_in_seconds: period_duration_in_seconds, + period_duration_in_seconds: period_duration_in_seconds }; let vesting_pool_map = vector[pool_config]; create_vesting_without_staking_pools(vesting_pool_map); diff --git a/aptos-move/framework/supra-framework/sources/genesis.spec.move b/aptos-move/framework/supra-framework/sources/genesis.spec.move index f5dfcc59d532f..09dad93f2d356 100644 --- a/aptos-move/framework/supra-framework/sources/genesis.spec.move +++ b/aptos-move/framework/supra-framework/sources/genesis.spec.move @@ -149,7 +149,8 @@ spec supra_framework::genesis { let addr = std::signer::address_of(supra_framework); aborts_if addr != @supra_framework; aborts_if exists(@supra_framework); - ensures global(@supra_framework) == chain_status::GenesisEndMarker {}; + ensures global(@supra_framework) + == chain_status::GenesisEndMarker {}; } spec create_pbo_delegation_pools { @@ -181,7 +182,10 @@ spec supra_framework::genesis { } spec schema CompareTimeRequires { - let staking_rewards_config = global(@supra_framework); - requires staking_rewards_config.last_rewards_rate_period_start_in_secs <= timestamp::spec_now_seconds(); + let staking_rewards_config = global( + @supra_framework + ); + requires staking_rewards_config.last_rewards_rate_period_start_in_secs + <= timestamp::spec_now_seconds(); } } diff --git a/aptos-move/framework/supra-framework/sources/guid.move b/aptos-move/framework/supra-framework/sources/guid.move index d6029775af550..bf4d97315e2fa 100644 --- a/aptos-move/framework/supra-framework/sources/guid.move +++ b/aptos-move/framework/supra-framework/sources/guid.move @@ -23,12 +23,7 @@ module supra_framework::guid { public(friend) fun create(addr: address, creation_num_ref: &mut u64): GUID { let creation_num = *creation_num_ref; *creation_num_ref = creation_num + 1; - GUID { - id: ID { - creation_num, - addr, - } - } + GUID { id: ID { creation_num, addr } } } /// Create a non-privileged id from `addr` and `creation_num` diff --git a/aptos-move/framework/supra-framework/sources/jwks.move b/aptos-move/framework/supra-framework/sources/jwks.move index 11a684633a487..02388b82e1eb3 100644 --- a/aptos-move/framework/supra-framework/sources/jwks.move +++ b/aptos-move/framework/supra-framework/sources/jwks.move @@ -45,19 +45,19 @@ module supra_framework::jwks { /// The ut8-8 encoded OpenID configuration URL of the provider. /// E.g., b"https://www.facebook.com/.well-known/openid-configuration/". - config_url: vector, + config_url: vector } /// A list of OIDC providers whose JWKs should be watched by validators. Maintained by governance proposals. struct SupportedOIDCProviders has copy, drop, key, store { - providers: vector, + providers: vector } /// An JWK variant that represents the JWKs which were observed but not yet supported by Supra. /// Observing `UnsupportedJWK`s means the providers adopted a new key type/format, and the system should be updated. struct UnsupportedJWK has copy, drop, store { id: vector, - payload: vector, + payload: vector } /// A JWK variant where `kty` is `RSA`. @@ -66,7 +66,7 @@ module supra_framework::jwks { kty: String, alg: String, e: String, - n: String, + n: String } /// A JSON web key. @@ -75,7 +75,7 @@ module supra_framework::jwks { /// Currently the variant type is one of the following. /// - `RSA_JWK` /// - `UnsupportedJWK` - variant: Any, + variant: Any } /// A provider and its `JWK`s. @@ -90,25 +90,25 @@ module supra_framework::jwks { version: u64, /// Vector of `JWK`'s sorted by their unique ID (from `get_jwk_id`) in dictionary order. - jwks: vector, + jwks: vector } /// Multiple `ProviderJWKs` objects, indexed by issuer and key ID. struct AllProvidersJWKs has copy, drop, store { /// Vector of `ProviderJWKs` sorted by `ProviderJWKs::issuer` in dictionary order. - entries: vector, + entries: vector } /// The `AllProvidersJWKs` that validators observed and agreed on. struct ObservedJWKs has copy, drop, key, store { - jwks: AllProvidersJWKs, + jwks: AllProvidersJWKs } #[event] /// When `ObservedJWKs` is updated, this event is sent to resync the JWK consensus state in all validators. struct ObservedJWKsUpdated has drop, store { epoch: u64, - jwks: AllProvidersJWKs, + jwks: AllProvidersJWKs } /// A small edit or patch that is applied to a `AllProvidersJWKs` to obtain `PatchedJWKs`. @@ -119,7 +119,7 @@ module supra_framework::jwks { /// - `PatchRemoveIssuer` /// - `PatchRemoveJWK` /// - `PatchUpsertJWK` - variant: Any, + variant: Any } /// A `Patch` variant to remove all JWKs. @@ -127,32 +127,32 @@ module supra_framework::jwks { /// A `Patch` variant to remove an issuer and all its JWKs. struct PatchRemoveIssuer has copy, drop, store { - issuer: vector, + issuer: vector } /// A `Patch` variant to remove a specific JWK of an issuer. struct PatchRemoveJWK has copy, drop, store { issuer: vector, - jwk_id: vector, + jwk_id: vector } /// A `Patch` variant to upsert a JWK for an issuer. struct PatchUpsertJWK has copy, drop, store { issuer: vector, - jwk: JWK, + jwk: JWK } /// A sequence of `Patch` objects that are applied *one by one* to the `ObservedJWKs`. /// /// Maintained by governance proposals. struct Patches has key { - patches: vector, + patches: vector } /// The result of applying the `Patches` to the `ObservedJWKs`. /// This is what applications should consume. struct PatchedJWKs has drop, key { - jwks: AllProvidersJWKs, + jwks: AllProvidersJWKs } // @@ -169,7 +169,9 @@ module supra_framework::jwks { /// Get a JWK by issuer and key ID from the `PatchedJWKs`, if it exists. /// More convenient to call from Move, since it does not abort. - public fun try_get_patched_jwk(issuer: vector, jwk_id: vector): Option acquires PatchedJWKs { + public fun try_get_patched_jwk( + issuer: vector, jwk_id: vector + ): Option acquires PatchedJWKs { let jwks = &borrow_global(@supra_framework).jwks; try_get_jwk_by_issuer(jwks, issuer, jwk_id) } @@ -177,13 +179,15 @@ module supra_framework::jwks { /// Deprecated by `upsert_oidc_provider_for_next_epoch()`. /// /// TODO: update all the tests that reference this function, then disable this function. - public fun upsert_oidc_provider(fx: &signer, name: vector, config_url: vector): Option> acquires SupportedOIDCProviders { + public fun upsert_oidc_provider( + fx: &signer, name: vector, config_url: vector + ): Option> acquires SupportedOIDCProviders { system_addresses::assert_supra_framework(fx); chain_status::assert_genesis(); let provider_set = borrow_global_mut(@supra_framework); - let old_config_url= remove_oidc_provider_internal(provider_set, name); + let old_config_url = remove_oidc_provider_internal(provider_set, name); vector::push_back(&mut provider_set.providers, OIDCProvider { name, config_url }); old_config_url } @@ -198,14 +202,17 @@ module supra_framework::jwks { /// ); /// supra_framework::aptos_governance::reconfigure(&framework_signer); /// ``` - public fun upsert_oidc_provider_for_next_epoch(fx: &signer, name: vector, config_url: vector): Option> acquires SupportedOIDCProviders { + public fun upsert_oidc_provider_for_next_epoch( + fx: &signer, name: vector, config_url: vector + ): Option> acquires SupportedOIDCProviders { system_addresses::assert_supra_framework(fx); - let provider_set = if (config_buffer::does_exist()) { - config_buffer::extract() - } else { - *borrow_global_mut(@supra_framework) - }; + let provider_set = + if (config_buffer::does_exist()) { + config_buffer::extract() + } else { + *borrow_global_mut(@supra_framework) + }; let old_config_url = remove_oidc_provider_internal(&mut provider_set, name); vector::push_back(&mut provider_set.providers, OIDCProvider { name, config_url }); @@ -216,7 +223,9 @@ module supra_framework::jwks { /// Deprecated by `remove_oidc_provider_for_next_epoch()`. /// /// TODO: update all the tests that reference this function, then disable this function. - public fun remove_oidc_provider(fx: &signer, name: vector): Option> acquires SupportedOIDCProviders { + public fun remove_oidc_provider( + fx: &signer, name: vector + ): Option> acquires SupportedOIDCProviders { system_addresses::assert_supra_framework(fx); chain_status::assert_genesis(); @@ -233,14 +242,17 @@ module supra_framework::jwks { /// ); /// supra_framework::aptos_governance::reconfigure(&framework_signer); /// ``` - public fun remove_oidc_provider_for_next_epoch(fx: &signer, name: vector): Option> acquires SupportedOIDCProviders { + public fun remove_oidc_provider_for_next_epoch( + fx: &signer, name: vector + ): Option> acquires SupportedOIDCProviders { system_addresses::assert_supra_framework(fx); - let provider_set = if (config_buffer::does_exist()) { - config_buffer::extract() - } else { - *borrow_global_mut(@supra_framework) - }; + let provider_set = + if (config_buffer::does_exist()) { + config_buffer::extract() + } else { + *borrow_global_mut(@supra_framework) + }; let ret = remove_oidc_provider_internal(&mut provider_set, name); config_buffer::upsert(provider_set); ret @@ -260,7 +272,9 @@ module supra_framework::jwks { } /// Set the `Patches`. Only called in governance proposals. - public fun set_patches(fx: &signer, patches: vector) acquires Patches, PatchedJWKs, ObservedJWKs { + public fun set_patches( + fx: &signer, patches: vector + ) acquires Patches, PatchedJWKs, ObservedJWKs { system_addresses::assert_supra_framework(fx); borrow_global_mut(@supra_framework).patches = patches; regenerate_patched_jwks(); @@ -269,19 +283,21 @@ module supra_framework::jwks { /// Create a `Patch` that removes all entries. public fun new_patch_remove_all(): Patch { Patch { - variant: copyable_any::pack(PatchRemoveAll {}), + variant: copyable_any::pack(PatchRemoveAll {}) } } /// Create a `Patch` that removes the entry of a given issuer, if exists. public fun new_patch_remove_issuer(issuer: vector): Patch { Patch { - variant: copyable_any::pack(PatchRemoveIssuer { issuer }), + variant: copyable_any::pack(PatchRemoveIssuer { issuer }) } } /// Create a `Patch` that removes the entry of a given issuer, if exists. - public fun new_patch_remove_jwk(issuer: vector, jwk_id: vector): Patch { + public fun new_patch_remove_jwk( + issuer: vector, jwk_id: vector + ): Patch { Patch { variant: copyable_any::pack(PatchRemoveJWK { issuer, jwk_id }) } @@ -297,13 +313,9 @@ module supra_framework::jwks { /// Create a `JWK` of variant `RSA_JWK`. public fun new_rsa_jwk(kid: String, alg: String, e: String, n: String): JWK { JWK { - variant: copyable_any::pack(RSA_JWK { - kid, - kty: utf8(b"RSA"), - e, - n, - alg, - }), + variant: copyable_any::pack( + RSA_JWK { kid, kty: utf8(b"RSA"), e, n, alg } + ) } } @@ -318,18 +330,27 @@ module supra_framework::jwks { public fun initialize(fx: &signer) { system_addresses::assert_supra_framework(fx); move_to(fx, SupportedOIDCProviders { providers: vector[] }); - move_to(fx, ObservedJWKs { jwks: AllProvidersJWKs { entries: vector[] } }); + move_to(fx, ObservedJWKs { + jwks: AllProvidersJWKs { entries: vector[] } + }); move_to(fx, Patches { patches: vector[] }); - move_to(fx, PatchedJWKs { jwks: AllProvidersJWKs { entries: vector[] } }); + move_to(fx, PatchedJWKs { + jwks: AllProvidersJWKs { entries: vector[] } + }); } /// Helper function that removes an OIDC provider from the `SupportedOIDCProviders`. /// Returns the old config URL of the provider, if any, as an `Option`. - fun remove_oidc_provider_internal(provider_set: &mut SupportedOIDCProviders, name: vector): Option> { - let (name_exists, idx) = vector::find(&provider_set.providers, |obj| { - let provider: &OIDCProvider = obj; - provider.name == name - }); + fun remove_oidc_provider_internal( + provider_set: &mut SupportedOIDCProviders, name: vector + ): Option> { + let (name_exists, idx) = vector::find( + &provider_set.providers, + |obj| { + let provider: &OIDCProvider = obj; + provider.name == name + } + ); if (name_exists) { let old_provider = vector::swap_remove(&mut provider_set.providers, idx); @@ -343,13 +364,18 @@ module supra_framework::jwks { /// /// NOTE: It is assumed verification has been done to ensure each update is quorum-certified, /// and its `version` equals to the on-chain version + 1. - public fun upsert_into_observed_jwks(fx: &signer, provider_jwks_vec: vector) acquires ObservedJWKs, PatchedJWKs, Patches { + public fun upsert_into_observed_jwks( + fx: &signer, provider_jwks_vec: vector + ) acquires ObservedJWKs, PatchedJWKs, Patches { system_addresses::assert_supra_framework(fx); let observed_jwks = borrow_global_mut(@supra_framework); - vector::for_each(provider_jwks_vec, |obj| { - let provider_jwks: ProviderJWKs = obj; - upsert_provider_jwks(&mut observed_jwks.jwks, provider_jwks); - }); + vector::for_each( + provider_jwks_vec, + |obj| { + let provider_jwks: ProviderJWKs = obj; + upsert_provider_jwks(&mut observed_jwks.jwks, provider_jwks); + } + ); let epoch = reconfiguration::current_epoch(); emit(ObservedJWKsUpdated { epoch, jwks: observed_jwks.jwks }); @@ -359,7 +385,9 @@ module supra_framework::jwks { /// Only used by governance to delete an issuer from `ObservedJWKs`, if it exists. /// /// Return the potentially existing `ProviderJWKs` of the given issuer. - public fun remove_issuer_from_observed_jwks(fx: &signer, issuer: vector): Option acquires ObservedJWKs, PatchedJWKs, Patches { + public fun remove_issuer_from_observed_jwks( + fx: &signer, issuer: vector + ): Option acquires ObservedJWKs, PatchedJWKs, Patches { system_addresses::assert_supra_framework(fx); let observed_jwks = borrow_global_mut(@supra_framework); let old_value = remove_issuer(&mut observed_jwks.jwks, issuer); @@ -375,19 +403,27 @@ module supra_framework::jwks { fun regenerate_patched_jwks() acquires PatchedJWKs, Patches, ObservedJWKs { let jwks = borrow_global(@supra_framework).jwks; let patches = borrow_global(@supra_framework); - vector::for_each_ref(&patches.patches, |obj|{ - let patch: &Patch = obj; - apply_patch(&mut jwks, *patch); - }); + vector::for_each_ref( + &patches.patches, + |obj| { + let patch: &Patch = obj; + apply_patch(&mut jwks, *patch); + } + ); *borrow_global_mut(@supra_framework) = PatchedJWKs { jwks }; } /// Get a JWK by issuer and key ID from a `AllProvidersJWKs`, if it exists. - fun try_get_jwk_by_issuer(jwks: &AllProvidersJWKs, issuer: vector, jwk_id: vector): Option { - let (issuer_found, index) = vector::find(&jwks.entries, |obj| { - let provider_jwks: &ProviderJWKs = obj; - issuer == provider_jwks.issuer - }); + fun try_get_jwk_by_issuer( + jwks: &AllProvidersJWKs, issuer: vector, jwk_id: vector + ): Option { + let (issuer_found, index) = vector::find( + &jwks.entries, + |obj| { + let provider_jwks: &ProviderJWKs = obj; + issuer == provider_jwks.issuer + } + ); if (issuer_found) { try_get_jwk_by_id(vector::borrow(&jwks.entries, index), jwk_id) @@ -397,11 +433,16 @@ module supra_framework::jwks { } /// Get a JWK by key ID from a `ProviderJWKs`, if it exists. - fun try_get_jwk_by_id(provider_jwks: &ProviderJWKs, jwk_id: vector): Option { - let (jwk_id_found, index) = vector::find(&provider_jwks.jwks, |obj|{ - let jwk: &JWK = obj; - jwk_id == get_jwk_id(jwk) - }); + fun try_get_jwk_by_id( + provider_jwks: &ProviderJWKs, jwk_id: vector + ): Option { + let (jwk_id_found, index) = vector::find( + &provider_jwks.jwks, + |obj| { + let jwk: &JWK = obj; + jwk_id == get_jwk_id(jwk) + } + ); if (jwk_id_found) { option::some(*vector::borrow(&provider_jwks.jwks, index)) @@ -426,7 +467,9 @@ module supra_framework::jwks { /// Upsert a `ProviderJWKs` into an `AllProvidersJWKs`. If this upsert replaced an existing entry, return it. /// Maintains the sorted-by-issuer invariant in `AllProvidersJWKs`. - fun upsert_provider_jwks(jwks: &mut AllProvidersJWKs, provider_jwks: ProviderJWKs): Option { + fun upsert_provider_jwks( + jwks: &mut AllProvidersJWKs, provider_jwks: ProviderJWKs + ): Option { // NOTE: Using a linear-time search here because we do not expect too many providers. let found = false; let index = 0; @@ -444,15 +487,16 @@ module supra_framework::jwks { // Now if `found == true`, `index` points to the JWK we want to update/remove; otherwise, `index` points to // where we want to insert. - let ret = if (found) { - let entry = vector::borrow_mut(&mut jwks.entries, index); - let old_entry = option::some(*entry); - *entry = provider_jwks; - old_entry - } else { - vector::insert(&mut jwks.entries, index, provider_jwks); - option::none() - }; + let ret = + if (found) { + let entry = vector::borrow_mut(&mut jwks.entries, index); + let old_entry = option::some(*entry); + *entry = provider_jwks; + old_entry + } else { + vector::insert(&mut jwks.entries, index, provider_jwks); + option::none() + }; ret } @@ -460,16 +504,20 @@ module supra_framework::jwks { /// Remove the entry of an issuer from a `AllProvidersJWKs` and return the entry, if exists. /// Maintains the sorted-by-issuer invariant in `AllProvidersJWKs`. fun remove_issuer(jwks: &mut AllProvidersJWKs, issuer: vector): Option { - let (found, index) = vector::find(&jwks.entries, |obj| { - let provider_jwk_set: &ProviderJWKs = obj; - provider_jwk_set.issuer == issuer - }); + let (found, index) = vector::find( + &jwks.entries, + |obj| { + let provider_jwk_set: &ProviderJWKs = obj; + provider_jwk_set.issuer == issuer + } + ); - let ret = if (found) { - option::some(vector::remove(&mut jwks.entries, index)) - } else { - option::none() - }; + let ret = + if (found) { + option::some(vector::remove(&mut jwks.entries, index)) + } else { + option::none() + }; ret } @@ -492,31 +540,36 @@ module supra_framework::jwks { // Now if `found == true`, `index` points to the JWK we want to update/remove; otherwise, `index` points to // where we want to insert. - let ret = if (found) { - let entry = vector::borrow_mut(&mut set.jwks, index); - let old_entry = option::some(*entry); - *entry = jwk; - old_entry - } else { - vector::insert(&mut set.jwks, index, jwk); - option::none() - }; + let ret = + if (found) { + let entry = vector::borrow_mut(&mut set.jwks, index); + let old_entry = option::some(*entry); + *entry = jwk; + old_entry + } else { + vector::insert(&mut set.jwks, index, jwk); + option::none() + }; ret } /// Remove the entry of a key ID from a `ProviderJWKs` and return the entry, if exists. fun remove_jwk(jwks: &mut ProviderJWKs, jwk_id: vector): Option { - let (found, index) = vector::find(&jwks.jwks, |obj| { - let jwk: &JWK = obj; - jwk_id == get_jwk_id(jwk) - }); + let (found, index) = vector::find( + &jwks.jwks, + |obj| { + let jwk: &JWK = obj; + jwk_id == get_jwk_id(jwk) + } + ); - let ret = if (found) { - option::some(vector::remove(&mut jwks.jwks, index)) - } else { - option::none() - }; + let ret = + if (found) { + option::some(vector::remove(&mut jwks.jwks, index)) + } else { + option::none() + }; ret } @@ -545,15 +598,12 @@ module supra_framework::jwks { // TODO: This is inefficient: we remove the issuer, modify its JWKs & and reinsert the updated issuer. Why // not just update it in place? let existing_jwk_set = remove_issuer(jwks, cmd.issuer); - let jwk_set = if (option::is_some(&existing_jwk_set)) { - option::extract(&mut existing_jwk_set) - } else { - ProviderJWKs { - version: 0, - issuer: cmd.issuer, - jwks: vector[], - } - }; + let jwk_set = + if (option::is_some(&existing_jwk_set)) { + option::extract(&mut existing_jwk_set) + } else { + ProviderJWKs { version: 0, issuer: cmd.issuer, jwks: vector[] } + }; upsert_jwk(&mut jwk_set, cmd.jwk); upsert_provider_jwks(jwks, jwk_set); } else { @@ -587,31 +637,25 @@ module supra_framework::jwks { let alice_jwks_v1 = ProviderJWKs { issuer: b"alice", version: 1, - jwks: vector[jwk_0, jwk_1], + jwks: vector[jwk_0, jwk_1] }; - let bob_jwks_v1 = ProviderJWKs{ + let bob_jwks_v1 = ProviderJWKs { issuer: b"bob", version: 1, - jwks: vector[jwk_2, jwk_3], + jwks: vector[jwk_2, jwk_3] }; upsert_into_observed_jwks(fx, vector[bob_jwks_v1]); upsert_into_observed_jwks(fx, vector[alice_jwks_v1]); - let expected = AllProvidersJWKs { entries: vector[ - alice_jwks_v1, - bob_jwks_v1, - ] }; + let expected = AllProvidersJWKs { entries: vector[alice_jwks_v1, bob_jwks_v1] }; assert!(expected == borrow_global(@supra_framework).jwks, 2); let alice_jwks_v2 = ProviderJWKs { issuer: b"alice", version: 2, - jwks: vector[jwk_1, jwk_4], + jwks: vector[jwk_1, jwk_4] }; upsert_into_observed_jwks(fx, vector[alice_jwks_v2]); - let expected = AllProvidersJWKs { entries: vector[ - alice_jwks_v2, - bob_jwks_v1, - ] }; + let expected = AllProvidersJWKs { entries: vector[alice_jwks_v2, bob_jwks_v1] }; assert!(expected == borrow_global(@supra_framework).jwks, 3); remove_issuer_from_observed_jwks(fx, b"alice"); @@ -631,95 +675,126 @@ module supra_framework::jwks { utf8(b"e4adfb436b9e197e2e1106af2c842284e4986aff"), // kid utf8(b"RS256"), // alg utf8(b"AQAB"), // e - utf8(b"psply8S991RswM0JQJwv51fooFFvZUtYdL8avyKObshyzj7oJuJD8vkf5DKJJF1XOGi6Wv2D-U4b3htgrVXeOjAvaKTYtrQVUG_Txwjebdm2EvBJ4R6UaOULjavcSkb8VzW4l4AmP_yWoidkHq8n6vfHt9alDAONILi7jPDzRC7NvnHQ_x0hkRVh_OAmOJCpkgb0gx9-U8zSBSmowQmvw15AZ1I0buYZSSugY7jwNS2U716oujAiqtRkC7kg4gPouW_SxMleeo8PyRsHpYCfBME66m-P8Zr9Fh1Qgmqg4cWdy_6wUuNc1cbVY_7w1BpHZtZCNeQ56AHUgUFmo2LAQQ"), // n + utf8( + b"psply8S991RswM0JQJwv51fooFFvZUtYdL8avyKObshyzj7oJuJD8vkf5DKJJF1XOGi6Wv2D-U4b3htgrVXeOjAvaKTYtrQVUG_Txwjebdm2EvBJ4R6UaOULjavcSkb8VzW4l4AmP_yWoidkHq8n6vfHt9alDAONILi7jPDzRC7NvnHQ_x0hkRVh_OAmOJCpkgb0gx9-U8zSBSmowQmvw15AZ1I0buYZSSugY7jwNS2U716oujAiqtRkC7kg4gPouW_SxMleeo8PyRsHpYCfBME66m-P8Zr9Fh1Qgmqg4cWdy_6wUuNc1cbVY_7w1BpHZtZCNeQ56AHUgUFmo2LAQQ" + ) // n ), - new_unsupported_jwk(b"key_id_0", b"key_content_0"), - ], + new_unsupported_jwk(b"key_id_0", b"key_content_0") + ] }, ProviderJWKs { issuer: b"bob", version: 222, jwks: vector[ new_unsupported_jwk(b"key_id_1", b"key_content_1"), - new_unsupported_jwk(b"key_id_2", b"key_content_2"), - ], - }, - ], + new_unsupported_jwk(b"key_id_2", b"key_content_2") + ] + } + ] }; let patch = new_patch_remove_issuer(b"alice"); apply_patch(&mut jwks, patch); - assert!(jwks == AllProvidersJWKs { - entries: vector[ - ProviderJWKs { - issuer: b"bob", - version: 222, - jwks: vector[ - new_unsupported_jwk(b"key_id_1", b"key_content_1"), - new_unsupported_jwk(b"key_id_2", b"key_content_2"), - ], + assert!( + jwks + == AllProvidersJWKs { + entries: vector[ + ProviderJWKs { + issuer: b"bob", + version: 222, + jwks: vector[ + new_unsupported_jwk(b"key_id_1", b"key_content_1"), + new_unsupported_jwk(b"key_id_2", b"key_content_2") + ] + } + ] }, - ], - }, 1); + 1 + ); let patch = new_patch_remove_jwk(b"bob", b"key_id_1"); apply_patch(&mut jwks, patch); - assert!(jwks == AllProvidersJWKs { - entries: vector[ - ProviderJWKs { - issuer: b"bob", - version: 222, - jwks: vector[ - new_unsupported_jwk(b"key_id_2", b"key_content_2"), - ], + assert!( + jwks + == AllProvidersJWKs { + entries: vector[ + ProviderJWKs { + issuer: b"bob", + version: 222, + jwks: vector[new_unsupported_jwk( + b"key_id_2", b"key_content_2" + )] + } + ] }, - ], - }, 1); - - let patch = new_patch_upsert_jwk(b"carl", new_rsa_jwk( - utf8(b"0ad1fec78504f447bae65bcf5afaedb65eec9e81"), // kid - utf8(b"RS256"), // alg - utf8(b"AQAB"), // e - utf8(b"sm72oBH-R2Rqt4hkjp66tz5qCtq42TMnVgZg2Pdm_zs7_-EoFyNs9sD1MKsZAFaBPXBHDiWywyaHhLgwETLN9hlJIZPzGCEtV3mXJFSYG-8L6t3kyKi9X1lUTZzbmNpE0tf-eMW-3gs3VQSBJQOcQnuiANxbSXwS3PFmi173C_5fDSuC1RoYGT6X3JqLc3DWUmBGucuQjPaUF0w6LMqEIy0W_WYbW7HImwANT6dT52T72md0JWZuAKsRRnRr_bvaUX8_e3K8Pb1K_t3dD6WSLvtmEfUnGQgLynVl3aV5sRYC0Hy_IkRgoxl2fd8AaZT1X_rdPexYpx152Pl_CHJ79Q"), // n - )); + 1 + ); + + let patch = + new_patch_upsert_jwk( + b"carl", + new_rsa_jwk( + utf8(b"0ad1fec78504f447bae65bcf5afaedb65eec9e81"), // kid + utf8(b"RS256"), // alg + utf8(b"AQAB"), // e + utf8( + b"sm72oBH-R2Rqt4hkjp66tz5qCtq42TMnVgZg2Pdm_zs7_-EoFyNs9sD1MKsZAFaBPXBHDiWywyaHhLgwETLN9hlJIZPzGCEtV3mXJFSYG-8L6t3kyKi9X1lUTZzbmNpE0tf-eMW-3gs3VQSBJQOcQnuiANxbSXwS3PFmi173C_5fDSuC1RoYGT6X3JqLc3DWUmBGucuQjPaUF0w6LMqEIy0W_WYbW7HImwANT6dT52T72md0JWZuAKsRRnRr_bvaUX8_e3K8Pb1K_t3dD6WSLvtmEfUnGQgLynVl3aV5sRYC0Hy_IkRgoxl2fd8AaZT1X_rdPexYpx152Pl_CHJ79Q" + ) // n + ) + ); apply_patch(&mut jwks, patch); - let edit = new_patch_upsert_jwk(b"bob", new_unsupported_jwk(b"key_id_2", b"key_content_2b")); + let edit = + new_patch_upsert_jwk( + b"bob", new_unsupported_jwk(b"key_id_2", b"key_content_2b") + ); apply_patch(&mut jwks, edit); - let edit = new_patch_upsert_jwk(b"alice", new_unsupported_jwk(b"key_id_3", b"key_content_3")); + let edit = + new_patch_upsert_jwk( + b"alice", new_unsupported_jwk(b"key_id_3", b"key_content_3") + ); apply_patch(&mut jwks, edit); - let edit = new_patch_upsert_jwk(b"alice", new_unsupported_jwk(b"key_id_0", b"key_content_0b")); + let edit = + new_patch_upsert_jwk( + b"alice", new_unsupported_jwk(b"key_id_0", b"key_content_0b") + ); apply_patch(&mut jwks, edit); - assert!(jwks == AllProvidersJWKs { - entries: vector[ - ProviderJWKs { - issuer: b"alice", - version: 0, - jwks: vector[ - new_unsupported_jwk(b"key_id_0", b"key_content_0b"), - new_unsupported_jwk(b"key_id_3", b"key_content_3"), - ], - }, - ProviderJWKs { - issuer: b"bob", - version: 222, - jwks: vector[ - new_unsupported_jwk(b"key_id_2", b"key_content_2b"), - ], - }, - ProviderJWKs { - issuer: b"carl", - version: 0, - jwks: vector[ - new_rsa_jwk( - utf8(b"0ad1fec78504f447bae65bcf5afaedb65eec9e81"), // kid - utf8(b"RS256"), // alg - utf8(b"AQAB"), // e - utf8(b"sm72oBH-R2Rqt4hkjp66tz5qCtq42TMnVgZg2Pdm_zs7_-EoFyNs9sD1MKsZAFaBPXBHDiWywyaHhLgwETLN9hlJIZPzGCEtV3mXJFSYG-8L6t3kyKi9X1lUTZzbmNpE0tf-eMW-3gs3VQSBJQOcQnuiANxbSXwS3PFmi173C_5fDSuC1RoYGT6X3JqLc3DWUmBGucuQjPaUF0w6LMqEIy0W_WYbW7HImwANT6dT52T72md0JWZuAKsRRnRr_bvaUX8_e3K8Pb1K_t3dD6WSLvtmEfUnGQgLynVl3aV5sRYC0Hy_IkRgoxl2fd8AaZT1X_rdPexYpx152Pl_CHJ79Q"), // n - ) - ], + assert!( + jwks + == AllProvidersJWKs { + entries: vector[ + ProviderJWKs { + issuer: b"alice", + version: 0, + jwks: vector[ + new_unsupported_jwk(b"key_id_0", b"key_content_0b"), + new_unsupported_jwk(b"key_id_3", b"key_content_3") + ] + }, + ProviderJWKs { + issuer: b"bob", + version: 222, + jwks: vector[new_unsupported_jwk( + b"key_id_2", b"key_content_2b" + )] + }, + ProviderJWKs { + issuer: b"carl", + version: 0, + jwks: vector[ + new_rsa_jwk( + utf8(b"0ad1fec78504f447bae65bcf5afaedb65eec9e81"), // kid + utf8(b"RS256"), // alg + utf8(b"AQAB"), // e + utf8( + b"sm72oBH-R2Rqt4hkjp66tz5qCtq42TMnVgZg2Pdm_zs7_-EoFyNs9sD1MKsZAFaBPXBHDiWywyaHhLgwETLN9hlJIZPzGCEtV3mXJFSYG-8L6t3kyKi9X1lUTZzbmNpE0tf-eMW-3gs3VQSBJQOcQnuiANxbSXwS3PFmi173C_5fDSuC1RoYGT6X3JqLc3DWUmBGucuQjPaUF0w6LMqEIy0W_WYbW7HImwANT6dT52T72md0JWZuAKsRRnRr_bvaUX8_e3K8Pb1K_t3dD6WSLvtmEfUnGQgLynVl3aV5sRYC0Hy_IkRgoxl2fd8AaZT1X_rdPexYpx152Pl_CHJ79Q" + ) // n + ) + ] + } + ] }, - ], - }, 1); + 1 + ); let patch = new_patch_remove_all(); apply_patch(&mut jwks, patch); @@ -736,40 +811,37 @@ module supra_framework::jwks { let jwk_3b = new_unsupported_jwk(b"key_id_3", b"key_payload_3b"); // Fake observation from validators. - upsert_into_observed_jwks(&supra_framework, vector [ - ProviderJWKs { - issuer: b"alice", - version: 111, - jwks: vector[jwk_0, jwk_1], - }, - ProviderJWKs{ - issuer: b"bob", - version: 222, - jwks: vector[jwk_2, jwk_3], - }, - ]); + upsert_into_observed_jwks( + &supra_framework, + vector[ + ProviderJWKs { issuer: b"alice", version: 111, jwks: vector[jwk_0, jwk_1] }, + ProviderJWKs { issuer: b"bob", version: 222, jwks: vector[jwk_2, jwk_3] } + ] + ); assert!(jwk_3 == get_patched_jwk(b"bob", b"key_id_3"), 1); assert!(option::some(jwk_3) == try_get_patched_jwk(b"bob", b"key_id_3"), 1); // Ignore all Bob's keys. - set_patches(&supra_framework, vector[ - new_patch_remove_issuer(b"bob"), - ]); + set_patches(&supra_framework, vector[new_patch_remove_issuer(b"bob")]); assert!(option::none() == try_get_patched_jwk(b"bob", b"key_id_3"), 1); // Update one of Bob's key.. - set_patches(&supra_framework, vector[ - new_patch_upsert_jwk(b"bob", jwk_3b), - ]); + set_patches( + &supra_framework, + vector[new_patch_upsert_jwk(b"bob", jwk_3b)] + ); assert!(jwk_3b == get_patched_jwk(b"bob", b"key_id_3"), 1); assert!(option::some(jwk_3b) == try_get_patched_jwk(b"bob", b"key_id_3"), 1); // Wipe everything, then add some keys back. - set_patches(&supra_framework, vector[ - new_patch_remove_all(), - new_patch_upsert_jwk(b"alice", jwk_1), - new_patch_upsert_jwk(b"bob", jwk_3), - ]); + set_patches( + &supra_framework, + vector[ + new_patch_remove_all(), + new_patch_upsert_jwk(b"alice", jwk_1), + new_patch_upsert_jwk(b"bob", jwk_3) + ] + ); assert!(jwk_3 == get_patched_jwk(b"bob", b"key_id_3"), 1); assert!(option::some(jwk_3) == try_get_patched_jwk(b"bob", b"key_id_3"), 1); } diff --git a/aptos-move/framework/supra-framework/sources/keyless_account.move b/aptos-move/framework/supra-framework/sources/keyless_account.move index 5ed6f97505d0d..42bab487f1789 100644 --- a/aptos-move/framework/supra-framework/sources/keyless_account.move +++ b/aptos-move/framework/supra-framework/sources/keyless_account.move @@ -17,7 +17,7 @@ module supra_framework::keyless_account { friend supra_framework::reconfiguration_with_dkg; /// The training wheels PK needs to be 32 bytes long. - const E_TRAINING_WHEELS_PK_WRONG_SIZE : u64 = 1; + const E_TRAINING_WHEELS_PK_WRONG_SIZE: u64 = 1; /// A serialized BN254 G1 point is invalid. const E_INVALID_BN254_G1_SERIALIZATION: u64 = 2; @@ -41,7 +41,7 @@ module supra_framework::keyless_account { delta_g2: vector, /// `\forall i \in {0, ..., \ell}, 64-byte serialization of gamma^{-1} * (beta * a_i + alpha * b_i + c_i) * H`, where /// `H` is the generator of `G1` and `\ell` is 1 for the ZK relation. - gamma_abc_g1: vector>, + gamma_abc_g1: vector> } #[resource_group_member(group = supra_framework::keyless_account::Group)] @@ -64,30 +64,27 @@ module supra_framework::keyless_account { /// The max length of the JWT field name and value (e.g., `"max_age":"18"`) supported in our circuit max_extra_field_bytes: u16, /// The max length of the base64url-encoded JWT header in bytes supported in our circuit - max_jwt_header_b64_bytes: u32, + max_jwt_header_b64_bytes: u32 } #[test_only] - public fun initialize_for_test(fx: &signer, vk: Groth16VerificationKey, constants: Configuration) { + public fun initialize_for_test( + fx: &signer, vk: Groth16VerificationKey, constants: Configuration + ) { system_addresses::assert_supra_framework(fx); move_to(fx, vk); move_to(fx, constants); } - public fun new_groth16_verification_key(alpha_g1: vector, - beta_g2: vector, - gamma_g2: vector, - delta_g2: vector, - gamma_abc_g1: vector> + public fun new_groth16_verification_key( + alpha_g1: vector, + beta_g2: vector, + gamma_g2: vector, + delta_g2: vector, + gamma_abc_g1: vector> ): Groth16VerificationKey { - Groth16VerificationKey { - alpha_g1, - beta_g2, - gamma_g2, - delta_g2, - gamma_abc_g1, - } + Groth16VerificationKey { alpha_g1, beta_g2, gamma_g2, delta_g2, gamma_abc_g1 } } public fun new_configuration( @@ -108,19 +105,54 @@ module supra_framework::keyless_account { max_commited_epk_bytes, max_iss_val_bytes, max_extra_field_bytes, - max_jwt_header_b64_bytes, + max_jwt_header_b64_bytes } } /// Pre-validate the VK to actively-prevent incorrect VKs from being set on-chain. fun validate_groth16_vk(vk: &Groth16VerificationKey) { // Could be leveraged to speed up the VM deserialization of the VK by 2x, since it can assume the points are valid. - assert!(option::is_some(&crypto_algebra::deserialize(&vk.alpha_g1)), E_INVALID_BN254_G1_SERIALIZATION); - assert!(option::is_some(&crypto_algebra::deserialize(&vk.beta_g2)), E_INVALID_BN254_G2_SERIALIZATION); - assert!(option::is_some(&crypto_algebra::deserialize(&vk.gamma_g2)), E_INVALID_BN254_G2_SERIALIZATION); - assert!(option::is_some(&crypto_algebra::deserialize(&vk.delta_g2)), E_INVALID_BN254_G2_SERIALIZATION); + assert!( + option::is_some( + &crypto_algebra::deserialize( + &vk.alpha_g1 + ) + ), + E_INVALID_BN254_G1_SERIALIZATION + ); + assert!( + option::is_some( + &crypto_algebra::deserialize( + &vk.beta_g2 + ) + ), + E_INVALID_BN254_G2_SERIALIZATION + ); + assert!( + option::is_some( + &crypto_algebra::deserialize( + &vk.gamma_g2 + ) + ), + E_INVALID_BN254_G2_SERIALIZATION + ); + assert!( + option::is_some( + &crypto_algebra::deserialize( + &vk.delta_g2 + ) + ), + E_INVALID_BN254_G2_SERIALIZATION + ); for (i in 0..vector::length(&vk.gamma_abc_g1)) { - assert!(option::is_some(&crypto_algebra::deserialize(vector::borrow(&vk.gamma_abc_g1, i))), E_INVALID_BN254_G1_SERIALIZATION); + assert!( + option::is_some( + &crypto_algebra::deserialize( + vector::borrow(&vk.gamma_abc_g1, i) + ) + ), + E_INVALID_BN254_G1_SERIALIZATION + ); }; } @@ -128,7 +160,9 @@ module supra_framework::keyless_account { /// `set_groth16_verification_key_for_next_epoch`. /// /// WARNING: See `set_groth16_verification_key_for_next_epoch` for caveats. - public fun update_groth16_verification_key(fx: &signer, vk: Groth16VerificationKey) { + public fun update_groth16_verification_key( + fx: &signer, vk: Groth16VerificationKey + ) { system_addresses::assert_supra_framework(fx); chain_status::assert_genesis(); // There should not be a previous resource set here. @@ -152,7 +186,9 @@ module supra_framework::keyless_account { chain_status::assert_genesis(); if (option::is_some(&pk)) { - assert!(vector::length(option::borrow(&pk)) == 32, E_TRAINING_WHEELS_PK_WRONG_SIZE) + assert!( + vector::length(option::borrow(&pk)) == 32, E_TRAINING_WHEELS_PK_WRONG_SIZE + ) }; let config = borrow_global_mut(signer::address_of(fx)); @@ -160,7 +196,9 @@ module supra_framework::keyless_account { } #[deprecated] - public fun update_max_exp_horizon(fx: &signer, max_exp_horizon_secs: u64) acquires Configuration { + public fun update_max_exp_horizon( + fx: &signer, max_exp_horizon_secs: u64 + ) acquires Configuration { system_addresses::assert_supra_framework(fx); chain_status::assert_genesis(); @@ -193,18 +231,21 @@ module supra_framework::keyless_account { /// so that old ZKPs for the old VK cannot be replayed as potentially-valid ZKPs. /// /// WARNING: If a malicious key is set, this would lead to stolen funds. - public fun set_groth16_verification_key_for_next_epoch(fx: &signer, vk: Groth16VerificationKey) { + public fun set_groth16_verification_key_for_next_epoch( + fx: &signer, vk: Groth16VerificationKey + ) { system_addresses::assert_supra_framework(fx); config_buffer::upsert(vk); } - /// Queues up a change to the keyless configuration. The change will only be effective after reconfiguration. Only /// callable via governance proposal. /// /// WARNING: A malicious `Configuration` could lead to DoS attacks, create liveness issues, or enable a malicious /// recovery service provider to phish users' accounts. - public fun set_configuration_for_next_epoch(fx: &signer, config: Configuration) { + public fun set_configuration_for_next_epoch( + fx: &signer, config: Configuration + ) { system_addresses::assert_supra_framework(fx); config_buffer::upsert(config); } @@ -213,7 +254,9 @@ module supra_framework::keyless_account { /// reconfiguration. Only callable via governance proposal. /// /// WARNING: If a malicious key is set, this *could* lead to stolen funds. - public fun update_training_wheels_for_next_epoch(fx: &signer, pk: Option>) acquires Configuration { + public fun update_training_wheels_for_next_epoch( + fx: &signer, pk: Option> + ) acquires Configuration { system_addresses::assert_supra_framework(fx); // If a PK is being set, validate it first. @@ -223,11 +266,12 @@ module supra_framework::keyless_account { assert!(option::is_some(&vpk), E_TRAINING_WHEELS_PK_WRONG_SIZE) }; - let config = if (config_buffer::does_exist()) { - config_buffer::extract() - } else { - *borrow_global(signer::address_of(fx)) - }; + let config = + if (config_buffer::does_exist()) { + config_buffer::extract() + } else { + *borrow_global(signer::address_of(fx)) + }; config.training_wheels_pubkey = pk; @@ -236,14 +280,17 @@ module supra_framework::keyless_account { /// Convenience method to queues up a change to the max expiration horizon. The change will only be effective after /// reconfiguration. Only callable via governance proposal. - public fun update_max_exp_horizon_for_next_epoch(fx: &signer, max_exp_horizon_secs: u64) acquires Configuration { + public fun update_max_exp_horizon_for_next_epoch( + fx: &signer, max_exp_horizon_secs: u64 + ) acquires Configuration { system_addresses::assert_supra_framework(fx); - let config = if (config_buffer::does_exist()) { - config_buffer::extract() - } else { - *borrow_global(signer::address_of(fx)) - }; + let config = + if (config_buffer::does_exist()) { + config_buffer::extract() + } else { + *borrow_global(signer::address_of(fx)) + }; config.max_exp_horizon_secs = max_exp_horizon_secs; @@ -258,11 +305,12 @@ module supra_framework::keyless_account { public fun remove_all_override_auds_for_next_epoch(fx: &signer) acquires Configuration { system_addresses::assert_supra_framework(fx); - let config = if (config_buffer::does_exist()) { - config_buffer::extract() - } else { - *borrow_global(signer::address_of(fx)) - }; + let config = + if (config_buffer::does_exist()) { + config_buffer::extract() + } else { + *borrow_global(signer::address_of(fx)) + }; config.override_aud_vals = vector[]; @@ -276,11 +324,12 @@ module supra_framework::keyless_account { public fun add_override_aud_for_next_epoch(fx: &signer, aud: String) acquires Configuration { system_addresses::assert_supra_framework(fx); - let config = if (config_buffer::does_exist()) { - config_buffer::extract() - } else { - *borrow_global(signer::address_of(fx)) - }; + let config = + if (config_buffer::does_exist()) { + config_buffer::extract() + } else { + *borrow_global(signer::address_of(fx)) + }; vector::push_back(&mut config.override_aud_vals, aud); diff --git a/aptos-move/framework/supra-framework/sources/keyless_account.spec.move b/aptos-move/framework/supra-framework/sources/keyless_account.spec.move index c3f0045eb1a69..e68aa73a4e556 100644 --- a/aptos-move/framework/supra-framework/sources/keyless_account.spec.move +++ b/aptos-move/framework/supra-framework/sources/keyless_account.spec.move @@ -1,6 +1,6 @@ spec supra_framework::keyless_account { spec module { // TODO: verification is disabled until this module is specified. - pragma verify=false; + pragma verify = false; } } diff --git a/aptos-move/framework/supra-framework/sources/managed_coin.move b/aptos-move/framework/supra-framework/sources/managed_coin.move index ef1176f8490ec..599c57aff41b1 100644 --- a/aptos-move/framework/supra-framework/sources/managed_coin.move +++ b/aptos-move/framework/supra-framework/sources/managed_coin.move @@ -24,7 +24,7 @@ module supra_framework::managed_coin { struct Capabilities has key { burn_cap: BurnCapability, freeze_cap: FreezeCapability, - mint_cap: MintCapability, + mint_cap: MintCapability } // @@ -32,15 +32,12 @@ module supra_framework::managed_coin { // /// Withdraw an `amount` of coin `CoinType` from `account` and burn it. - public entry fun burn( - account: &signer, - amount: u64, - ) acquires Capabilities { + public entry fun burn(account: &signer, amount: u64) acquires Capabilities { let account_addr = signer::address_of(account); assert!( exists>(account_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let capabilities = borrow_global>(account_addr); @@ -56,34 +53,34 @@ module supra_framework::managed_coin { name: vector, symbol: vector, decimals: u8, - monitor_supply: bool, + monitor_supply: bool ) { - let (burn_cap, freeze_cap, mint_cap) = coin::initialize( + let (burn_cap, freeze_cap, mint_cap) = + coin::initialize( + account, + string::utf8(name), + string::utf8(symbol), + decimals, + monitor_supply + ); + + move_to( account, - string::utf8(name), - string::utf8(symbol), - decimals, - monitor_supply, + Capabilities { burn_cap, freeze_cap, mint_cap } ); - - move_to(account, Capabilities { - burn_cap, - freeze_cap, - mint_cap, - }); } /// Create new coins `CoinType` and deposit them into dst_addr's account. public entry fun mint( account: &signer, dst_addr: address, - amount: u64, + amount: u64 ) acquires Capabilities { let account_addr = signer::address_of(account); assert!( exists>(account_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let capabilities = borrow_global>(account_addr); @@ -112,15 +109,15 @@ module supra_framework::managed_coin { #[test(source = @0xa11ce, destination = @0xb0b, mod_account = @0x1)] public entry fun test_end_to_end( - source: signer, - destination: signer, - mod_account: signer + source: signer, destination: signer, mod_account: signer ) acquires Capabilities { let source_addr = signer::address_of(&source); let destination_addr = signer::address_of(&destination); supra_framework::account::create_account_for_test(source_addr); supra_framework::account::create_account_for_test(destination_addr); - supra_framework::account::create_account_for_test(signer::address_of(&mod_account)); + supra_framework::account::create_account_for_test( + signer::address_of(&mod_account) + ); aggregator_factory::initialize_aggregator_factory_for_test(&mod_account); initialize( @@ -163,13 +160,17 @@ module supra_framework::managed_coin { public entry fun fail_mint( source: signer, destination: signer, - mod_account: signer, + mod_account: signer ) acquires Capabilities { let source_addr = signer::address_of(&source); supra_framework::account::create_account_for_test(source_addr); - supra_framework::account::create_account_for_test(signer::address_of(&destination)); - supra_framework::account::create_account_for_test(signer::address_of(&mod_account)); + supra_framework::account::create_account_for_test( + signer::address_of(&destination) + ); + supra_framework::account::create_account_for_test( + signer::address_of(&mod_account) + ); aggregator_factory::initialize_aggregator_factory_for_test(&mod_account); initialize(&mod_account, b"Fake money", b"FMD", 1, true); @@ -185,13 +186,17 @@ module supra_framework::managed_coin { public entry fun fail_burn( source: signer, destination: signer, - mod_account: signer, + mod_account: signer ) acquires Capabilities { let source_addr = signer::address_of(&source); supra_framework::account::create_account_for_test(source_addr); - supra_framework::account::create_account_for_test(signer::address_of(&destination)); - supra_framework::account::create_account_for_test(signer::address_of(&mod_account)); + supra_framework::account::create_account_for_test( + signer::address_of(&destination) + ); + supra_framework::account::create_account_for_test( + signer::address_of(&mod_account) + ); aggregator_factory::initialize_aggregator_factory_for_test(&mod_account); initialize(&mod_account, b"Fake money", b"FMD", 1, true); diff --git a/aptos-move/framework/supra-framework/sources/managed_coin.spec.move b/aptos-move/framework/supra-framework/sources/managed_coin.spec.move index b93ade231840b..1c148082ca63e 100644 --- a/aptos-move/framework/supra-framework/sources/managed_coin.spec.move +++ b/aptos-move/framework/supra-framework/sources/managed_coin.spec.move @@ -50,10 +50,7 @@ spec supra_framework::managed_coin { pragma aborts_if_is_strict; } - spec burn( - account: &signer, - amount: u64, - ) { + spec burn(account: &signer, amount: u64) { use aptos_std::type_info; // TODO(fa_migration) pragma verify = false; @@ -74,12 +71,12 @@ spec supra_framework::managed_coin { aborts_if coin_store.frozen; aborts_if balance < amount; - let addr = type_info::type_of().account_address; + let addr = type_info::type_of().account_address; let maybe_supply = global>(addr).supply; // Ensure the amount won't be overflow. aborts_if amount == 0; aborts_if !exists>(addr); - include coin::CoinSubAbortsIf { amount:amount }; + include coin::CoinSubAbortsIf { amount: amount }; // Ensure that the global 'supply' decreases by 'amount'. ensures coin::supply == old(coin::supply) - amount; @@ -95,7 +92,7 @@ spec supra_framework::managed_coin { name: vector, symbol: vector, decimals: u8, - monitor_supply: bool, + monitor_supply: bool ) { include coin::InitializeInternalSchema; aborts_if !string::spec_internal_check_utf8(name); @@ -108,11 +105,7 @@ spec supra_framework::managed_coin { /// The Capabilities should not exist in the signer address. /// The `dst_addr` should not be frozen. - spec mint( - account: &signer, - dst_addr: address, - amount: u64, - ) { + spec mint(account: &signer, dst_addr: address, amount: u64) { use aptos_std::type_info; // TODO(fa_migration) pragma verify = false; @@ -127,7 +120,8 @@ spec supra_framework::managed_coin { include coin::CoinAddAbortsIf; ensures coin::supply == old(coin::supply) + amount; /// [high-level-req-6] - ensures global>(dst_addr).coin.value == old(global>(dst_addr)).coin.value + amount; + ensures global>(dst_addr).coin.value + == old(global>(dst_addr)).coin.value + amount; } /// An account can only be registered once. @@ -141,10 +135,14 @@ spec supra_framework::managed_coin { let account_addr = signer::address_of(account); let acc = global(account_addr); - aborts_if !exists>(account_addr) && acc.guid_creation_num + 2 >= account::MAX_GUID_CREATION_NUM; - aborts_if !exists>(account_addr) && acc.guid_creation_num + 2 > MAX_U64; - aborts_if !exists>(account_addr) && !exists(account_addr); - aborts_if !exists>(account_addr) && !type_info::spec_is_struct(); + aborts_if !exists>(account_addr) + && acc.guid_creation_num + 2 >= account::MAX_GUID_CREATION_NUM; + aborts_if !exists>(account_addr) + && acc.guid_creation_num + 2 > MAX_U64; + aborts_if !exists>(account_addr) + && !exists(account_addr); + aborts_if !exists>(account_addr) + && !type_info::spec_is_struct(); ensures exists>(account_addr); } } diff --git a/aptos-move/framework/supra-framework/sources/multisig_account.move b/aptos-move/framework/supra-framework/sources/multisig_account.move index 9a7e6a9fec862..2ed13f489c985 100644 --- a/aptos-move/framework/supra-framework/sources/multisig_account.move +++ b/aptos-move/framework/supra-framework/sources/multisig_account.move @@ -37,7 +37,12 @@ /// flat governance structure, clients are encouraged to write their own modules on top of this multisig account module /// and implement the governance voting logic on top. module supra_framework::multisig_account { - use supra_framework::account::{Self, SignerCapability, new_event_handle, create_resource_address}; + use supra_framework::account::{ + Self, + SignerCapability, + new_event_handle, + create_resource_address + }; use supra_framework::supra_coin::SupraCoin; use supra_framework::chain_id; use supra_framework::create_signer::create_signer; @@ -101,14 +106,13 @@ module supra_framework::multisig_account { /// The multisig v2 enhancement feature is not enabled. const EMULTISIG_V2_ENHANCEMENT_NOT_ENABLED: u64 = 20; /// The transaction has timed out and cannot be executed. - const ETRANSACTION_TIMED_OUT:u64 = 21; + const ETRANSACTION_TIMED_OUT: u64 = 21; /// Timeout duration must be at least 300 seconds. const EINVALID_TIMEOUT_DURATION: u64 = 22; /// Define the minimum timeout duration for a transaction. const MINIMAL_TIMEOUT_DURATION: u64 = 300; - const ZERO_AUTH_KEY: vector = x"0000000000000000000000000000000000000000000000000000000000000000"; const MAX_PENDING_TRANSACTIONS: u64 = 20; @@ -152,7 +156,7 @@ module supra_framework::multisig_account { execute_transaction_events: EventHandle, transaction_execution_failed_events: EventHandle, metadata_updated_events: EventHandle, - TimeoutDurationUpdatedEvent: EventHandle, + TimeoutDurationUpdatedEvent: EventHandle } /// A transaction to be executed in a multisig account. @@ -165,7 +169,7 @@ module supra_framework::multisig_account { // The owner who created this transaction. creator: address, // The timestamp in seconds when the transaction was created. - creation_time_secs: u64, + creation_time_secs: u64 } /// Contains information about execution failure. @@ -179,7 +183,7 @@ module supra_framework::multisig_account { // arithmetic failures. error_type: String, // The detailed error code explaining which error occurred. - error_code: u64, + error_code: u64 } /// Used only for verifying multisig account creation on top of existing accounts. @@ -194,7 +198,7 @@ module supra_framework::multisig_account { // The list of owners for the multisig account. owners: vector
, // The number of signatures required (signature threshold). - num_signatures_required: u64, + num_signatures_required: u64 } /// Used only for verifying multisig account creation on top of existing accounts and rotating the auth key to 0x0. @@ -209,49 +213,49 @@ module supra_framework::multisig_account { // The list of owners for the multisig account. owners: vector
, // The number of signatures required (signature threshold). - num_signatures_required: u64, + num_signatures_required: u64 } /// Event emitted when new owners are added to the multisig account. struct AddOwnersEvent has drop, store { - owners_added: vector
, + owners_added: vector
} #[event] struct AddOwners has drop, store { multisig_account: address, - owners_added: vector
, + owners_added: vector
} /// Event emitted when new owners are removed from the multisig account. struct RemoveOwnersEvent has drop, store { - owners_removed: vector
, + owners_removed: vector
} #[event] struct RemoveOwners has drop, store { multisig_account: address, - owners_removed: vector
, + owners_removed: vector
} /// Event emitted when the number of signatures required is updated. struct UpdateSignaturesRequiredEvent has drop, store { old_num_signatures_required: u64, - new_num_signatures_required: u64, + new_num_signatures_required: u64 } #[event] struct UpdateSignaturesRequired has drop, store { multisig_account: address, old_num_signatures_required: u64, - new_num_signatures_required: u64, + new_num_signatures_required: u64 } /// Event emitted when a transaction is created. struct CreateTransactionEvent has drop, store { creator: address, sequence_number: u64, - transaction: MultisigTransaction, + transaction: MultisigTransaction } #[event] @@ -259,14 +263,14 @@ module supra_framework::multisig_account { multisig_account: address, creator: address, sequence_number: u64, - transaction: MultisigTransaction, + transaction: MultisigTransaction } /// Event emitted when an owner approves or rejects a transaction. struct VoteEvent has drop, store { owner: address, sequence_number: u64, - approved: bool, + approved: bool } #[event] @@ -274,7 +278,7 @@ module supra_framework::multisig_account { multisig_account: address, owner: address, sequence_number: u64, - approved: bool, + approved: bool } /// Event emitted when a transaction is officially rejected because the number of rejections has reached the @@ -282,7 +286,7 @@ module supra_framework::multisig_account { struct ExecuteRejectedTransactionEvent has drop, store { sequence_number: u64, num_rejections: u64, - executor: address, + executor: address } #[event] @@ -290,7 +294,7 @@ module supra_framework::multisig_account { multisig_account: address, sequence_number: u64, num_rejections: u64, - executor: address, + executor: address } /// Event emitted when a transaction is executed. @@ -298,7 +302,7 @@ module supra_framework::multisig_account { executor: address, sequence_number: u64, transaction_payload: vector, - num_approvals: u64, + num_approvals: u64 } #[event] @@ -307,7 +311,7 @@ module supra_framework::multisig_account { executor: address, sequence_number: u64, transaction_payload: vector, - num_approvals: u64, + num_approvals: u64 } /// Event emitted when a transaction's execution failed. @@ -316,7 +320,7 @@ module supra_framework::multisig_account { sequence_number: u64, transaction_payload: vector, num_approvals: u64, - execution_error: ExecutionError, + execution_error: ExecutionError } #[event] @@ -326,34 +330,36 @@ module supra_framework::multisig_account { sequence_number: u64, transaction_payload: vector, num_approvals: u64, - execution_error: ExecutionError, + execution_error: ExecutionError } /// Event emitted when a transaction's metadata is updated. struct MetadataUpdatedEvent has drop, store { old_metadata: SimpleMap>, - new_metadata: SimpleMap>, + new_metadata: SimpleMap> } /// Event emitted when a transaction's timeout duration is updated. struct TimeoutDurationUpdatedEvent has drop, store { executor: address, old_timeout_duration: u64, - new_timeout_duration: u64, + new_timeout_duration: u64 } - + #[event] struct MetadataUpdated has drop, store { multisig_account: address, old_metadata: SimpleMap>, - new_metadata: SimpleMap>, + new_metadata: SimpleMap> } ////////////////////////// View functions /////////////////////////////// #[view] /// Return the multisig account's metadata. - public fun metadata(multisig_account: address): SimpleMap> acquires MultisigAccount { + public fun metadata( + multisig_account: address + ): SimpleMap> acquires MultisigAccount { borrow_global(multisig_account).metadata } @@ -385,13 +391,13 @@ module supra_framework::multisig_account { #[view] /// Return the transaction with the given transaction id. public fun get_transaction( - multisig_account: address, - sequence_number: u64, + multisig_account: address, sequence_number: u64 ): MultisigTransaction acquires MultisigAccount { let multisig_account_resource = borrow_global(multisig_account); assert!( - sequence_number > 0 && sequence_number < multisig_account_resource.next_sequence_number, - error::invalid_argument(EINVALID_SEQUENCE_NUMBER), + sequence_number > 0 + && sequence_number < multisig_account_resource.next_sequence_number, + error::invalid_argument(EINVALID_SEQUENCE_NUMBER) ); *table::borrow(&multisig_account_resource.transactions, sequence_number) } @@ -406,7 +412,10 @@ module supra_framework::multisig_account { let i = multisig_account.last_executed_sequence_number + 1; let next_sequence_number = multisig_account.next_sequence_number; while (i < next_sequence_number) { - vector::push_back(&mut pending_transactions, *table::borrow(&multisig_account.transactions, i)); + vector::push_back( + &mut pending_transactions, + *table::borrow(&multisig_account.transactions, i) + ); i = i + 1; }; pending_transactions @@ -415,10 +424,13 @@ module supra_framework::multisig_account { #[view] /// Return the payload for the next transaction in the queue. public fun get_next_transaction_payload( - multisig_account: address, provided_payload: vector): vector acquires MultisigAccount { + multisig_account: address, provided_payload: vector + ): vector acquires MultisigAccount { let multisig_account_resource = borrow_global(multisig_account); - let sequence_number = multisig_account_resource.last_executed_sequence_number + 1; - let transaction = table::borrow(&multisig_account_resource.transactions, sequence_number); + let sequence_number = multisig_account_resource.last_executed_sequence_number + + 1; + let transaction = + table::borrow(&multisig_account_resource.transactions, sequence_number); if (option::is_some(&transaction.payload)) { *option::borrow(&transaction.payload) @@ -429,91 +441,124 @@ module supra_framework::multisig_account { #[view] /// Return true if the transaction with given transaction id can be executed now. - public fun can_be_executed(multisig_account: address, sequence_number: u64): bool acquires MultisigAccount { + public fun can_be_executed( + multisig_account: address, sequence_number: u64 + ): bool acquires MultisigAccount { assert_valid_sequence_number(multisig_account, sequence_number); - let (num_approvals, _) = num_approvals_and_rejections(multisig_account, sequence_number); - sequence_number == last_resolved_sequence_number(multisig_account) + 1 && - num_approvals >= num_signatures_required(multisig_account) && - timeout_duration(multisig_account) >= now_seconds() - tx_creation_time_secs(multisig_account, sequence_number) + let (num_approvals, _) = + num_approvals_and_rejections(multisig_account, sequence_number); + sequence_number == last_resolved_sequence_number(multisig_account) + 1 + && num_approvals >= num_signatures_required(multisig_account) + && timeout_duration(multisig_account) + >= now_seconds() + - tx_creation_time_secs(multisig_account, sequence_number) } #[view] /// Return true if the owner can execute the transaction with given transaction id now. - public fun can_execute(owner: address, multisig_account: address, sequence_number: u64): bool acquires MultisigAccount { + public fun can_execute( + owner: address, multisig_account: address, sequence_number: u64 + ): bool acquires MultisigAccount { assert_valid_sequence_number(multisig_account, sequence_number); - let (num_approvals, _) = num_approvals_and_rejections(multisig_account, sequence_number); + let (num_approvals, _) = + num_approvals_and_rejections(multisig_account, sequence_number); if (!has_voted_for_approval(multisig_account, sequence_number, owner)) { num_approvals = num_approvals + 1; }; - is_owner(owner, multisig_account) && - sequence_number == last_resolved_sequence_number(multisig_account) + 1 && - num_approvals >= num_signatures_required(multisig_account) && - timeout_duration(multisig_account) >= now_seconds() - tx_creation_time_secs(multisig_account, sequence_number) + is_owner(owner, multisig_account) + && sequence_number == last_resolved_sequence_number(multisig_account) + 1 + && num_approvals >= num_signatures_required(multisig_account) + && timeout_duration(multisig_account) + >= now_seconds() + - tx_creation_time_secs(multisig_account, sequence_number) } #[view] /// Return true if the transaction with given transaction id can be officially rejected. - public fun can_be_rejected(multisig_account: address, sequence_number: u64): bool acquires MultisigAccount { + public fun can_be_rejected( + multisig_account: address, sequence_number: u64 + ): bool acquires MultisigAccount { assert_valid_sequence_number(multisig_account, sequence_number); - let (_, num_rejections) = num_approvals_and_rejections(multisig_account, sequence_number); - sequence_number == last_resolved_sequence_number(multisig_account) + 1 && - num_rejections >= num_signatures_required(multisig_account) || - timeout_duration(multisig_account) < now_seconds() - tx_creation_time_secs(multisig_account, sequence_number) + let (_, num_rejections) = + num_approvals_and_rejections(multisig_account, sequence_number); + sequence_number == last_resolved_sequence_number(multisig_account) + 1 + && num_rejections >= num_signatures_required(multisig_account) + || timeout_duration(multisig_account) + < now_seconds() + - tx_creation_time_secs(multisig_account, sequence_number) } #[view] /// Return true if the owner can execute the "rejected" transaction with given transaction id now. - public fun can_reject(owner: address, multisig_account: address, sequence_number: u64): bool acquires MultisigAccount { + public fun can_reject( + owner: address, multisig_account: address, sequence_number: u64 + ): bool acquires MultisigAccount { assert_valid_sequence_number(multisig_account, sequence_number); - let (_, num_rejections) = num_approvals_and_rejections(multisig_account, sequence_number); + let (_, num_rejections) = + num_approvals_and_rejections(multisig_account, sequence_number); if (!has_voted_for_rejection(multisig_account, sequence_number, owner)) { num_rejections = num_rejections + 1; }; - is_owner(owner, multisig_account) && - sequence_number == last_resolved_sequence_number(multisig_account) + 1 && - num_rejections >= num_signatures_required(multisig_account) || - timeout_duration(multisig_account) < now_seconds() - tx_creation_time_secs(multisig_account, sequence_number) + is_owner(owner, multisig_account) + && sequence_number == last_resolved_sequence_number(multisig_account) + 1 + && num_rejections >= num_signatures_required(multisig_account) + || timeout_duration(multisig_account) + < now_seconds() + - tx_creation_time_secs(multisig_account, sequence_number) } #[view] /// Return the predicted address for the next multisig account if created from the given creator address. public fun get_next_multisig_account_address(creator: address): address { let owner_nonce = account::get_sequence_number(creator); - create_resource_address(&creator, create_multisig_account_seed(to_bytes(&owner_nonce))) + create_resource_address( + &creator, create_multisig_account_seed(to_bytes(&owner_nonce)) + ) } #[view] /// Return the id of the last transaction that was executed (successful or failed) or removed. - public fun last_resolved_sequence_number(multisig_account: address): u64 acquires MultisigAccount { - let multisig_account_resource = borrow_global_mut(multisig_account); + public fun last_resolved_sequence_number( + multisig_account: address + ): u64 acquires MultisigAccount { + let multisig_account_resource = + borrow_global_mut(multisig_account); multisig_account_resource.last_executed_sequence_number } #[view] /// Return the id of the last transaction that was executed (successful or failed) or removed. - public fun tx_creation_time_secs(multisig_account: address, sequence_number: u64): u64 acquires MultisigAccount { + public fun tx_creation_time_secs( + multisig_account: address, sequence_number: u64 + ): u64 acquires MultisigAccount { let multisig_account_resource = borrow_global(multisig_account); - let transaction = table::borrow(&multisig_account_resource.transactions, sequence_number); + let transaction = + table::borrow(&multisig_account_resource.transactions, sequence_number); transaction.creation_time_secs } #[view] /// Return the id of the next transaction created. public fun next_sequence_number(multisig_account: address): u64 acquires MultisigAccount { - let multisig_account_resource = borrow_global_mut(multisig_account); + let multisig_account_resource = + borrow_global_mut(multisig_account); multisig_account_resource.next_sequence_number } #[view] /// Return a bool tuple indicating whether an owner has voted and if so, whether they voted yes or no. public fun vote( - multisig_account: address, sequence_number: u64, owner: address): (bool, bool) acquires MultisigAccount { - let multisig_account_resource = borrow_global_mut(multisig_account); + multisig_account: address, sequence_number: u64, owner: address + ): (bool, bool) acquires MultisigAccount { + let multisig_account_resource = + borrow_global_mut(multisig_account); assert!( - sequence_number > 0 && sequence_number < multisig_account_resource.next_sequence_number, - error::invalid_argument(EINVALID_SEQUENCE_NUMBER), + sequence_number > 0 + && sequence_number < multisig_account_resource.next_sequence_number, + error::invalid_argument(EINVALID_SEQUENCE_NUMBER) ); - let transaction = table::borrow(&multisig_account_resource.transactions, sequence_number); + let transaction = + table::borrow(&multisig_account_resource.transactions, sequence_number); let votes = &transaction.votes; let voted = simple_map::contains_key(votes, &owner); let vote = voted && *simple_map::borrow(votes, &owner); @@ -521,12 +566,16 @@ module supra_framework::multisig_account { } #[view] - public fun available_transaction_queue_capacity(multisig_account: address): u64 acquires MultisigAccount { - let multisig_account_resource = borrow_global_mut(multisig_account); - let num_pending_transactions = multisig_account_resource.next_sequence_number - multisig_account_resource.last_executed_sequence_number - 1; - if (num_pending_transactions > MAX_PENDING_TRANSACTIONS) { - 0 - } else { + public fun available_transaction_queue_capacity( + multisig_account: address + ): u64 acquires MultisigAccount { + let multisig_account_resource = + borrow_global_mut(multisig_account); + let num_pending_transactions = + multisig_account_resource.next_sequence_number + - multisig_account_resource.last_executed_sequence_number - 1; + if (num_pending_transactions > MAX_PENDING_TRANSACTIONS) { 0 } + else { MAX_PENDING_TRANSACTIONS - num_pending_transactions } } @@ -551,9 +600,12 @@ module supra_framework::multisig_account { create_multisig_account_signed_message: vector, metadata_keys: vector, metadata_values: vector>, - timeout_duration: u64, + timeout_duration: u64 ) acquires MultisigAccount { - assert!(timeout_duration >= MINIMAL_TIMEOUT_DURATION, error::invalid_argument(EINVALID_TIMEOUT_DURATION)); + assert!( + timeout_duration >= MINIMAL_TIMEOUT_DURATION, + error::invalid_argument(EINVALID_TIMEOUT_DURATION) + ); // Verify that the `MultisigAccountCreationMessage` has the right information and is signed by the account // owner's key. let proof_challenge = MultisigAccountCreationMessage { @@ -561,14 +613,14 @@ module supra_framework::multisig_account { account_address: multisig_address, sequence_number: account::get_sequence_number(multisig_address), owners, - num_signatures_required, + num_signatures_required }; account::verify_signed_message( multisig_address, account_scheme, account_public_key, create_multisig_account_signed_message, - proof_challenge, + proof_challenge ); // We create the signer for the multisig account here since this is required to add the MultisigAccount resource @@ -600,9 +652,12 @@ module supra_framework::multisig_account { create_multisig_account_signed_message: vector, metadata_keys: vector, metadata_values: vector>, - timeout_duration: u64, + timeout_duration: u64 ) acquires MultisigAccount { - assert!(timeout_duration >= MINIMAL_TIMEOUT_DURATION, error::invalid_argument(EINVALID_TIMEOUT_DURATION)); + assert!( + timeout_duration >= MINIMAL_TIMEOUT_DURATION, + error::invalid_argument(EINVALID_TIMEOUT_DURATION) + ); // Verify that the `MultisigAccountCreationMessage` has the right information and is signed by the account // owner's key. let proof_challenge = MultisigAccountCreationWithAuthKeyRevocationMessage { @@ -610,14 +665,14 @@ module supra_framework::multisig_account { account_address: multisig_address, sequence_number: account::get_sequence_number(multisig_address), owners, - num_signatures_required, + num_signatures_required }; account::verify_signed_message( multisig_address, account_scheme, account_public_key, create_multisig_account_signed_message, - proof_challenge, + proof_challenge ); // We create the signer for the multisig account here since this is required to add the MultisigAccount resource @@ -653,9 +708,16 @@ module supra_framework::multisig_account { num_signatures_required: u64, metadata_keys: vector, metadata_values: vector>, - timeout_duration: u64, + timeout_duration: u64 ) acquires MultisigAccount { - create_with_owners(owner, vector[], num_signatures_required, metadata_keys, metadata_values, timeout_duration); + create_with_owners( + owner, + vector[], + num_signatures_required, + metadata_keys, + metadata_values, + timeout_duration + ); } /// Creates a new multisig account with the specified additional owner list and signatures required. @@ -670,9 +732,12 @@ module supra_framework::multisig_account { num_signatures_required: u64, metadata_keys: vector, metadata_values: vector>, - timeout_duration: u64, + timeout_duration: u64 ) acquires MultisigAccount { - assert!(timeout_duration >= MINIMAL_TIMEOUT_DURATION, error::invalid_argument(EINVALID_TIMEOUT_DURATION)); + assert!( + timeout_duration >= MINIMAL_TIMEOUT_DURATION, + error::invalid_argument(EINVALID_TIMEOUT_DURATION) + ); let (multisig_account, multisig_signer_cap) = create_multisig_account(owner); vector::push_back(&mut additional_owners, address_of(owner)); create_with_owners_internal( @@ -682,7 +747,7 @@ module supra_framework::multisig_account { option::some(multisig_signer_cap), metadata_keys, metadata_values, - timeout_duration, + timeout_duration ); } @@ -696,7 +761,7 @@ module supra_framework::multisig_account { num_signatures_required: u64, metadata_keys: vector, metadata_values: vector>, - timeout_duration: u64, + timeout_duration: u64 ) acquires MultisigAccount { let bootstrapper_address = address_of(bootstrapper); create_with_owners( @@ -705,7 +770,7 @@ module supra_framework::multisig_account { num_signatures_required, metadata_keys, metadata_values, - timeout_duration, + timeout_duration ); update_owner_schema( get_next_multisig_account_address(bootstrapper_address), @@ -722,37 +787,56 @@ module supra_framework::multisig_account { multisig_account_signer_cap: Option, metadata_keys: vector, metadata_values: vector>, - timeout_duration: u64, + timeout_duration: u64 ) acquires MultisigAccount { - assert!(features::multisig_accounts_enabled(), error::unavailable(EMULTISIG_ACCOUNTS_NOT_ENABLED_YET)); assert!( - num_signatures_required > 0 && num_signatures_required <= vector::length(&owners), - error::invalid_argument(EINVALID_SIGNATURES_REQUIRED), + features::multisig_accounts_enabled(), + error::unavailable(EMULTISIG_ACCOUNTS_NOT_ENABLED_YET) + ); + assert!( + num_signatures_required > 0 + && num_signatures_required <= vector::length(&owners), + error::invalid_argument(EINVALID_SIGNATURES_REQUIRED) ); let multisig_address = address_of(multisig_account); validate_owners(&owners, multisig_address); - move_to(multisig_account, MultisigAccount { - owners, - num_signatures_required, - transactions: table::new(), - metadata: simple_map::create>(), - // First transaction will start at id 1 instead of 0. - last_executed_sequence_number: 0, - next_sequence_number: 1, - signer_cap: multisig_account_signer_cap, - timeout_duration, - add_owners_events: new_event_handle(multisig_account), - remove_owners_events: new_event_handle(multisig_account), - update_signature_required_events: new_event_handle(multisig_account), - create_transaction_events: new_event_handle(multisig_account), - vote_events: new_event_handle(multisig_account), - execute_rejected_transaction_events: new_event_handle(multisig_account), - execute_transaction_events: new_event_handle(multisig_account), - transaction_execution_failed_events: new_event_handle(multisig_account), - metadata_updated_events: new_event_handle(multisig_account), - TimeoutDurationUpdatedEvent: new_event_handle(multisig_account), - }); + move_to( + multisig_account, + MultisigAccount { + owners, + num_signatures_required, + transactions: table::new(), + metadata: simple_map::create>(), + // First transaction will start at id 1 instead of 0. + last_executed_sequence_number: 0, + next_sequence_number: 1, + signer_cap: multisig_account_signer_cap, + timeout_duration, + add_owners_events: new_event_handle(multisig_account), + remove_owners_events: new_event_handle( + multisig_account + ), + update_signature_required_events: new_event_handle< + UpdateSignaturesRequiredEvent>(multisig_account), + create_transaction_events: new_event_handle( + multisig_account + ), + vote_events: new_event_handle(multisig_account), + execute_rejected_transaction_events: new_event_handle< + ExecuteRejectedTransactionEvent>(multisig_account), + execute_transaction_events: new_event_handle< + TransactionExecutionSucceededEvent>(multisig_account), + transaction_execution_failed_events: new_event_handle< + TransactionExecutionFailedEvent>(multisig_account), + metadata_updated_events: new_event_handle( + multisig_account + ), + TimeoutDurationUpdatedEvent: new_event_handle( + multisig_account + ) + } + ); update_metadata_internal(multisig_account, metadata_keys, metadata_values, false); } @@ -771,7 +855,8 @@ module supra_framework::multisig_account { /// ensures that a multisig transaction cannot lead to another module obtaining the multisig signer and using it to /// maliciously alter the owners list. entry fun add_owners( - multisig_account: &signer, new_owners: vector
) acquires MultisigAccount { + multisig_account: &signer, new_owners: vector
+ ) acquires MultisigAccount { update_owner_schema( address_of(multisig_account), new_owners, @@ -796,7 +881,8 @@ module supra_framework::multisig_account { /// Similar to remove_owners, but only allow removing one owner. entry fun remove_owner( - multisig_account: &signer, owner_to_remove: address) acquires MultisigAccount { + multisig_account: &signer, owner_to_remove: address + ) acquires MultisigAccount { remove_owners(multisig_account, vector[owner_to_remove]); } @@ -808,7 +894,8 @@ module supra_framework::multisig_account { /// ensures that a multisig transaction cannot lead to another module obtaining the multisig signer and using it to /// maliciously alter the owners list. entry fun remove_owners( - multisig_account: &signer, owners_to_remove: vector
) acquires MultisigAccount { + multisig_account: &signer, owners_to_remove: vector
+ ) acquires MultisigAccount { update_owner_schema( address_of(multisig_account), vector[], @@ -819,9 +906,7 @@ module supra_framework::multisig_account { /// Swap an owner in for an old one, without changing required signatures. entry fun swap_owner( - multisig_account: &signer, - to_swap_in: address, - to_swap_out: address + multisig_account: &signer, to_swap_in: address, to_swap_out: address ) acquires MultisigAccount { update_owner_schema( address_of(multisig_account), @@ -867,7 +952,8 @@ module supra_framework::multisig_account { /// ensures that a multisig transaction cannot lead to another module obtaining the multisig signer and using it to /// maliciously alter the number of signatures required. entry fun update_signatures_required( - multisig_account: &signer, new_num_signatures_required: u64) acquires MultisigAccount { + multisig_account: &signer, new_num_signatures_required: u64 + ) acquires MultisigAccount { update_owner_schema( address_of(multisig_account), vector[], @@ -884,7 +970,8 @@ module supra_framework::multisig_account { /// ensures that a multisig transaction cannot lead to another module obtaining the multisig signer and using it to /// maliciously alter the number of signatures required. entry fun update_metadata( - multisig_account: &signer, keys: vector, values: vector>) acquires MultisigAccount { + multisig_account: &signer, keys: vector, values: vector> + ) acquires MultisigAccount { update_metadata_internal(multisig_account, keys, values, true); } @@ -892,17 +979,18 @@ module supra_framework::multisig_account { multisig_account: &signer, keys: vector, values: vector>, - emit_event: bool, + emit_event: bool ) acquires MultisigAccount { let num_attributes = vector::length(&keys); assert!( num_attributes == vector::length(&values), - error::invalid_argument(ENUMBER_OF_METADATA_KEYS_AND_VALUES_DONT_MATCH), + error::invalid_argument(ENUMBER_OF_METADATA_KEYS_AND_VALUES_DONT_MATCH) ); let multisig_address = address_of(multisig_account); assert_multisig_account_exists(multisig_address); - let multisig_account_resource = borrow_global_mut(multisig_address); + let multisig_account_resource = + borrow_global_mut(multisig_address); let old_metadata = multisig_account_resource.metadata; multisig_account_resource.metadata = simple_map::create>(); let metadata = &mut multisig_account_resource.metadata; @@ -912,7 +1000,7 @@ module supra_framework::multisig_account { let value = *vector::borrow(&values, i); assert!( !simple_map::contains_key(metadata, &key), - error::invalid_argument(EDUPLICATE_METADATA_KEY), + error::invalid_argument(EDUPLICATE_METADATA_KEY) ); simple_map::add(metadata, key, value); @@ -925,7 +1013,7 @@ module supra_framework::multisig_account { MetadataUpdated { multisig_account: multisig_address, old_metadata, - new_metadata: multisig_account_resource.metadata, + new_metadata: multisig_account_resource.metadata } ) }; @@ -933,7 +1021,7 @@ module supra_framework::multisig_account { &mut multisig_account_resource.metadata_updated_events, MetadataUpdatedEvent { old_metadata, - new_metadata: multisig_account_resource.metadata, + new_metadata: multisig_account_resource.metadata } ); }; @@ -941,10 +1029,15 @@ module supra_framework::multisig_account { /// Update the timeout duration for the multisig account. entry fun update_timeout_duration( - multisig_account: &signer, timeout_duration: u64) acquires MultisigAccount { - assert!(timeout_duration >= MINIMAL_TIMEOUT_DURATION, error::invalid_argument(EINVALID_TIMEOUT_DURATION)); + multisig_account: &signer, timeout_duration: u64 + ) acquires MultisigAccount { + assert!( + timeout_duration >= MINIMAL_TIMEOUT_DURATION, + error::invalid_argument(EINVALID_TIMEOUT_DURATION) + ); assert_multisig_account_exists(address_of(multisig_account)); - let multisig_account_resource = borrow_global_mut(address_of(multisig_account)); + let multisig_account_resource = + borrow_global_mut(address_of(multisig_account)); let old_timeout_duration = multisig_account_resource.timeout_duration; multisig_account_resource.timeout_duration = timeout_duration; emit_event( @@ -952,7 +1045,7 @@ module supra_framework::multisig_account { TimeoutDurationUpdatedEvent { executor: address_of(multisig_account), old_timeout_duration, - new_timeout_duration: timeout_duration, + new_timeout_duration: timeout_duration } ); } @@ -963,9 +1056,13 @@ module supra_framework::multisig_account { public entry fun create_transaction( owner: &signer, multisig_account: address, - payload: vector, + payload: vector ) acquires MultisigAccount { - assert!(vector::length(&payload) > 0, error::invalid_argument(EPAYLOAD_CANNOT_BE_EMPTY)); + assert!( + vector::length(&payload) > 0, error::invalid_argument( + EPAYLOAD_CANNOT_BE_EMPTY + ) + ); assert_multisig_account_exists(multisig_account); assert_is_owner(owner, multisig_account); @@ -976,7 +1073,7 @@ module supra_framework::multisig_account { payload_hash: option::none>(), votes: simple_map::create(), creator, - creation_time_secs: now_seconds(), + creation_time_secs: now_seconds() }; add_transaction(creator, multisig_account, transaction); } @@ -987,10 +1084,13 @@ module supra_framework::multisig_account { public entry fun create_transaction_with_hash( owner: &signer, multisig_account: address, - payload_hash: vector, + payload_hash: vector ) acquires MultisigAccount { // Payload hash is a sha3-256 hash, so it must be exactly 32 bytes. - assert!(vector::length(&payload_hash) == 32, error::invalid_argument(EINVALID_PAYLOAD_HASH)); + assert!( + vector::length(&payload_hash) == 32, + error::invalid_argument(EINVALID_PAYLOAD_HASH) + ); assert_multisig_account_exists(multisig_account); assert_is_owner(owner, multisig_account); @@ -1001,20 +1101,22 @@ module supra_framework::multisig_account { payload_hash: option::some(payload_hash), votes: simple_map::create(), creator, - creation_time_secs: now_seconds(), + creation_time_secs: now_seconds() }; add_transaction(creator, multisig_account, transaction); } /// Approve a multisig transaction. public entry fun approve_transaction( - owner: &signer, multisig_account: address, sequence_number: u64) acquires MultisigAccount { + owner: &signer, multisig_account: address, sequence_number: u64 + ) acquires MultisigAccount { vote_transanction(owner, multisig_account, sequence_number, true); } /// Reject a multisig transaction. public entry fun reject_transaction( - owner: &signer, multisig_account: address, sequence_number: u64) acquires MultisigAccount { + owner: &signer, multisig_account: address, sequence_number: u64 + ) acquires MultisigAccount { vote_transanction(owner, multisig_account, sequence_number, false); } @@ -1022,16 +1124,24 @@ module supra_framework::multisig_account { /// Retained for backward compatibility: the function with the typographical error in its name /// will continue to be an accessible entry point. public entry fun vote_transanction( - owner: &signer, multisig_account: address, sequence_number: u64, approved: bool) acquires MultisigAccount { + owner: &signer, + multisig_account: address, + sequence_number: u64, + approved: bool + ) acquires MultisigAccount { assert_multisig_account_exists(multisig_account); - let multisig_account_resource = borrow_global_mut(multisig_account); + let multisig_account_resource = + borrow_global_mut(multisig_account); assert_is_owner_internal(owner, multisig_account_resource); assert!( table::contains(&multisig_account_resource.transactions, sequence_number), - error::not_found(ETRANSACTION_NOT_FOUND), + error::not_found(ETRANSACTION_NOT_FOUND) ); - let transaction = table::borrow_mut(&mut multisig_account_resource.transactions, sequence_number); + let transaction = + table::borrow_mut( + &mut multisig_account_resource.transactions, sequence_number + ); let votes = &mut transaction.votes; let owner_addr = address_of(owner); @@ -1043,37 +1153,43 @@ module supra_framework::multisig_account { if (std::features::module_event_migration_enabled()) { emit( - Vote { - multisig_account, - owner: owner_addr, - sequence_number, - approved, - } + Vote { multisig_account, owner: owner_addr, sequence_number, approved } ); }; emit_event( &mut multisig_account_resource.vote_events, - VoteEvent { - owner: owner_addr, - sequence_number, - approved, - } + VoteEvent { owner: owner_addr, sequence_number, approved } ); } /// Generic function that can be used to either approve or reject a multisig transaction public entry fun vote_transaction( - owner: &signer, multisig_account: address, sequence_number: u64, approved: bool) acquires MultisigAccount { - assert!(features::multisig_v2_enhancement_feature_enabled(), error::invalid_state(EMULTISIG_V2_ENHANCEMENT_NOT_ENABLED)); + owner: &signer, + multisig_account: address, + sequence_number: u64, + approved: bool + ) acquires MultisigAccount { + assert!( + features::multisig_v2_enhancement_feature_enabled(), + error::invalid_state(EMULTISIG_V2_ENHANCEMENT_NOT_ENABLED) + ); vote_transanction(owner, multisig_account, sequence_number, approved); } /// Generic function that can be used to either approve or reject a batch of transactions within a specified range. public entry fun vote_transactions( - owner: &signer, multisig_account: address, starting_sequence_number: u64, final_sequence_number: u64, approved: bool) acquires MultisigAccount { - assert!(features::multisig_v2_enhancement_feature_enabled(), error::invalid_state(EMULTISIG_V2_ENHANCEMENT_NOT_ENABLED)); + owner: &signer, + multisig_account: address, + starting_sequence_number: u64, + final_sequence_number: u64, + approved: bool + ) acquires MultisigAccount { + assert!( + features::multisig_v2_enhancement_feature_enabled(), + error::invalid_state(EMULTISIG_V2_ENHANCEMENT_NOT_ENABLED) + ); let sequence_number = starting_sequence_number; - while(sequence_number <= final_sequence_number) { + while (sequence_number <= final_sequence_number) { vote_transanction(owner, multisig_account, sequence_number, approved); sequence_number = sequence_number + 1; } @@ -1081,8 +1197,7 @@ module supra_framework::multisig_account { /// Remove the next transaction if it has sufficient owner rejections. public entry fun execute_rejected_transaction( - owner: &signer, - multisig_account: address, + owner: &signer, multisig_account: address ) acquires MultisigAccount { assert_multisig_account_exists(multisig_account); assert_is_owner(owner, multisig_account); @@ -1096,13 +1211,17 @@ module supra_framework::multisig_account { } }; - let multisig_account_resource = borrow_global_mut(multisig_account); - let creation_time_secs = table::borrow(&multisig_account_resource.transactions, sequence_number).creation_time_secs; + let multisig_account_resource = + borrow_global_mut(multisig_account); + let creation_time_secs = + table::borrow(&multisig_account_resource.transactions, sequence_number).creation_time_secs; let (_, num_rejections) = remove_executed_transaction(multisig_account_resource); assert!( // Can be removed if the number of rejections is greater than or equal to the number of signatures required or if the transaction has timed out. - num_rejections >= multisig_account_resource.num_signatures_required || multisig_account_resource.timeout_duration < now_seconds() - creation_time_secs, - error::invalid_state(ENOT_ENOUGH_REJECTIONS), + num_rejections >= multisig_account_resource.num_signatures_required + || multisig_account_resource.timeout_duration + < now_seconds() - creation_time_secs, + error::invalid_state(ENOT_ENOUGH_REJECTIONS) ); if (std::features::module_event_migration_enabled()) { @@ -1111,7 +1230,7 @@ module supra_framework::multisig_account { multisig_account, sequence_number, num_rejections, - executor: address_of(owner), + executor: address_of(owner) } ); }; @@ -1120,7 +1239,7 @@ module supra_framework::multisig_account { ExecuteRejectedTransactionEvent { sequence_number, num_rejections, - executor: owner_addr, + executor: owner_addr } ); } @@ -1129,12 +1248,21 @@ module supra_framework::multisig_account { public entry fun execute_rejected_transactions( owner: &signer, multisig_account: address, - final_sequence_number: u64, + final_sequence_number: u64 ) acquires MultisigAccount { - assert!(features::multisig_v2_enhancement_feature_enabled(), error::invalid_state(EMULTISIG_V2_ENHANCEMENT_NOT_ENABLED)); - assert!(last_resolved_sequence_number(multisig_account) < final_sequence_number, error::invalid_argument(EINVALID_SEQUENCE_NUMBER)); - assert!(final_sequence_number < next_sequence_number(multisig_account), error::invalid_argument(EINVALID_SEQUENCE_NUMBER)); - while(last_resolved_sequence_number(multisig_account) < final_sequence_number) { + assert!( + features::multisig_v2_enhancement_feature_enabled(), + error::invalid_state(EMULTISIG_V2_ENHANCEMENT_NOT_ENABLED) + ); + assert!( + last_resolved_sequence_number(multisig_account) < final_sequence_number, + error::invalid_argument(EINVALID_SEQUENCE_NUMBER) + ); + assert!( + final_sequence_number < next_sequence_number(multisig_account), + error::invalid_argument(EINVALID_SEQUENCE_NUMBER) + ); + while (last_resolved_sequence_number(multisig_account) < final_sequence_number) { execute_rejected_transaction(owner, multisig_account); } } @@ -1146,7 +1274,8 @@ module supra_framework::multisig_account { /// /// Transaction payload is optional if it's already stored on chain for the transaction. fun validate_multisig_transaction( - owner: &signer, multisig_account: address, payload: vector) acquires MultisigAccount { + owner: &signer, multisig_account: address, payload: vector + ) acquires MultisigAccount { assert_multisig_account_exists(multisig_account); assert_is_owner(owner, multisig_account); let sequence_number = last_resolved_sequence_number(multisig_account) + 1; @@ -1155,21 +1284,22 @@ module supra_framework::multisig_account { if (features::multisig_v2_enhancement_feature_enabled()) { assert!( can_execute(address_of(owner), multisig_account, sequence_number), - error::invalid_argument(ENOT_ENOUGH_APPROVALS), + error::invalid_argument(ENOT_ENOUGH_APPROVALS) ); - } - else { + } else { assert!( can_be_executed(multisig_account, sequence_number), - error::invalid_argument(ENOT_ENOUGH_APPROVALS), + error::invalid_argument(ENOT_ENOUGH_APPROVALS) ); }; let multisig_account_resource = borrow_global(multisig_account); - let transaction = table::borrow(&multisig_account_resource.transactions, sequence_number); + let transaction = + table::borrow(&multisig_account_resource.transactions, sequence_number); assert!( - multisig_account_resource.timeout_duration >= now_seconds() - transaction.creation_time_secs, - error::invalid_argument(ETRANSACTION_TIMED_OUT), + multisig_account_resource.timeout_duration + >= now_seconds() - transaction.creation_time_secs, + error::invalid_argument(ETRANSACTION_TIMED_OUT) ); // If the transaction payload is not stored on chain, verify that the provided payload matches the hashes stored @@ -1178,7 +1308,7 @@ module supra_framework::multisig_account { let payload_hash = option::borrow(&transaction.payload_hash); assert!( sha3_256(payload) == *payload_hash, - error::invalid_argument(EPAYLOAD_DOES_NOT_MATCH_HASH), + error::invalid_argument(EPAYLOAD_DOES_NOT_MATCH_HASH) ); }; @@ -1186,12 +1316,11 @@ module supra_framework::multisig_account { // verify that the provided payload matches the stored payload. if (features::abort_if_multisig_payload_mismatch_enabled() && option::is_some(&transaction.payload) - && !vector::is_empty(&payload) - ) { + && !vector::is_empty(&payload)) { let stored_payload = option::borrow(&transaction.payload); assert!( payload == *stored_payload, - error::invalid_argument(EPAYLOAD_DOES_NOT_MATCH), + error::invalid_argument(EPAYLOAD_DOES_NOT_MATCH) ); } } @@ -1201,10 +1330,12 @@ module supra_framework::multisig_account { fun successful_transaction_execution_cleanup( executor: address, multisig_account: address, - transaction_payload: vector, + transaction_payload: vector ) acquires MultisigAccount { - let num_approvals = transaction_execution_cleanup_common(executor, multisig_account); - let multisig_account_resource = borrow_global_mut(multisig_account); + let num_approvals = + transaction_execution_cleanup_common(executor, multisig_account); + let multisig_account_resource = + borrow_global_mut(multisig_account); if (std::features::module_event_migration_enabled()) { emit( TransactionExecutionSucceeded { @@ -1212,7 +1343,7 @@ module supra_framework::multisig_account { sequence_number: multisig_account_resource.last_executed_sequence_number, transaction_payload, num_approvals, - executor, + executor } ); }; @@ -1222,7 +1353,7 @@ module supra_framework::multisig_account { sequence_number: multisig_account_resource.last_executed_sequence_number, transaction_payload, num_approvals, - executor, + executor } ); } @@ -1233,10 +1364,12 @@ module supra_framework::multisig_account { executor: address, multisig_account: address, transaction_payload: vector, - execution_error: ExecutionError, + execution_error: ExecutionError ) acquires MultisigAccount { - let num_approvals = transaction_execution_cleanup_common(executor, multisig_account); - let multisig_account_resource = borrow_global_mut(multisig_account); + let num_approvals = + transaction_execution_cleanup_common(executor, multisig_account); + let multisig_account_resource = + borrow_global_mut(multisig_account); if (std::features::module_event_migration_enabled()) { emit( TransactionExecutionFailed { @@ -1245,7 +1378,7 @@ module supra_framework::multisig_account { sequence_number: multisig_account_resource.last_executed_sequence_number, transaction_payload, num_approvals, - execution_error, + execution_error } ); }; @@ -1256,18 +1389,22 @@ module supra_framework::multisig_account { sequence_number: multisig_account_resource.last_executed_sequence_number, transaction_payload, num_approvals, - execution_error, + execution_error } ); } ////////////////////////// Private functions /////////////////////////////// - inline fun transaction_execution_cleanup_common(executor: address, multisig_account: address): u64 acquires MultisigAccount { + inline fun transaction_execution_cleanup_common( + executor: address, multisig_account: address + ): u64 acquires MultisigAccount { let sequence_number = last_resolved_sequence_number(multisig_account) + 1; - let implicit_approval = !has_voted_for_approval(multisig_account, sequence_number, executor); + let implicit_approval = + !has_voted_for_approval(multisig_account, sequence_number, executor); - let multisig_account_resource = borrow_global_mut(multisig_account); + let multisig_account_resource = + borrow_global_mut(multisig_account); let (num_approvals, _) = remove_executed_transaction(multisig_account_resource); if (features::multisig_v2_enhancement_feature_enabled() && implicit_approval) { @@ -1277,18 +1414,14 @@ module supra_framework::multisig_account { multisig_account, owner: executor, sequence_number, - approved: true, + approved: true } ); }; num_approvals = num_approvals + 1; emit_event( &mut multisig_account_resource.vote_events, - VoteEvent { - owner: executor, - sequence_number, - approved: true, - } + VoteEvent { owner: executor, sequence_number, approved: true } ); }; @@ -1296,17 +1429,21 @@ module supra_framework::multisig_account { } // Remove the next transaction in the queue as it's been executed and return the number of approvals it had. - fun remove_executed_transaction(multisig_account_resource: &mut MultisigAccount): (u64, u64) { - let sequence_number = multisig_account_resource.last_executed_sequence_number + 1; - let transaction = table::remove(&mut multisig_account_resource.transactions, sequence_number); + fun remove_executed_transaction( + multisig_account_resource: &mut MultisigAccount + ): (u64, u64) { + let sequence_number = multisig_account_resource.last_executed_sequence_number + + 1; + let transaction = + table::remove(&mut multisig_account_resource.transactions, sequence_number); multisig_account_resource.last_executed_sequence_number = sequence_number; - num_approvals_and_rejections_internal(&multisig_account_resource.owners, &transaction) + num_approvals_and_rejections_internal( + &multisig_account_resource.owners, &transaction + ) } inline fun add_transaction( - creator: address, - multisig_account: address, - transaction: MultisigTransaction + creator: address, multisig_account: address, transaction: MultisigTransaction ) { if (features::multisig_v2_enhancement_feature_enabled()) { assert!( @@ -1315,29 +1452,39 @@ module supra_framework::multisig_account { ); }; - let multisig_account_resource = borrow_global_mut(multisig_account); + let multisig_account_resource = + borrow_global_mut(multisig_account); // The transaction creator also automatically votes for the transaction. simple_map::add(&mut transaction.votes, creator, true); let sequence_number = multisig_account_resource.next_sequence_number; multisig_account_resource.next_sequence_number = sequence_number + 1; - table::add(&mut multisig_account_resource.transactions, sequence_number, transaction); + table::add( + &mut multisig_account_resource.transactions, sequence_number, transaction + ); if (std::features::module_event_migration_enabled()) { emit( - CreateTransaction { multisig_account: multisig_account, creator, sequence_number, transaction } + CreateTransaction { + multisig_account: multisig_account, + creator, + sequence_number, + transaction + } ); }; emit_event( &mut multisig_account_resource.create_transaction_events, - CreateTransactionEvent { creator, sequence_number, transaction }, + CreateTransactionEvent { creator, sequence_number, transaction } ); } fun create_multisig_account(owner: &signer): (signer, SignerCapability) { let owner_nonce = account::get_sequence_number(address_of(owner)); let (multisig_signer, multisig_signer_cap) = - account::create_resource_account(owner, create_multisig_account_seed(to_bytes(&owner_nonce))); + account::create_resource_account( + owner, create_multisig_account_seed(to_bytes(&owner_nonce)) + ); // Register the account to receive SUPRA as this is not done by default as part of the resource account creation // flow. if (!coin::is_account_registered(address_of(&multisig_signer))) { @@ -1356,21 +1503,31 @@ module supra_framework::multisig_account { multisig_account_seed } - fun validate_owners(owners: &vector
, multisig_account: address) { + fun validate_owners( + owners: &vector
, multisig_account: address + ) { let distinct_owners: vector
= vector[]; - vector::for_each_ref(owners, |owner| { - let owner = *owner; - assert!(owner != multisig_account, error::invalid_argument(EOWNER_CANNOT_BE_MULTISIG_ACCOUNT_ITSELF)); - let (found, _) = vector::index_of(&distinct_owners, &owner); - assert!(!found, error::invalid_argument(EDUPLICATE_OWNER)); - vector::push_back(&mut distinct_owners, owner); - }); + vector::for_each_ref( + owners, + |owner| { + let owner = *owner; + assert!( + owner != multisig_account, + error::invalid_argument(EOWNER_CANNOT_BE_MULTISIG_ACCOUNT_ITSELF) + ); + let (found, _) = vector::index_of(&distinct_owners, &owner); + assert!(!found, error::invalid_argument(EDUPLICATE_OWNER)); + vector::push_back(&mut distinct_owners, owner); + } + ); } - inline fun assert_is_owner_internal(owner: &signer, multisig_account: &MultisigAccount) { + inline fun assert_is_owner_internal( + owner: &signer, multisig_account: &MultisigAccount + ) { assert!( vector::contains(&multisig_account.owners, &address_of(owner)), - error::permission_denied(ENOT_OWNER), + error::permission_denied(ENOT_OWNER) ); } @@ -1379,57 +1536,79 @@ module supra_framework::multisig_account { assert_is_owner_internal(owner, multisig_account_resource); } - inline fun num_approvals_and_rejections_internal(owners: &vector
, transaction: &MultisigTransaction): (u64, u64) { + inline fun num_approvals_and_rejections_internal( + owners: &vector
, transaction: &MultisigTransaction + ): (u64, u64) { let num_approvals = 0; let num_rejections = 0; let votes = &transaction.votes; - vector::for_each_ref(owners, |owner| { - if (simple_map::contains_key(votes, owner)) { - if (*simple_map::borrow(votes, owner)) { - num_approvals = num_approvals + 1; - } else { - num_rejections = num_rejections + 1; - }; + vector::for_each_ref( + owners, + |owner| { + if (simple_map::contains_key(votes, owner)) { + if (*simple_map::borrow(votes, owner)) { + num_approvals = num_approvals + 1; + } else { + num_rejections = num_rejections + 1; + }; + } } - }); + ); (num_approvals, num_rejections) } - inline fun num_approvals_and_rejections(multisig_account: address, sequence_number: u64): (u64, u64) acquires MultisigAccount { + inline fun num_approvals_and_rejections( + multisig_account: address, sequence_number: u64 + ): (u64, u64) acquires MultisigAccount { let multisig_account_resource = borrow_global(multisig_account); - let transaction = table::borrow(&multisig_account_resource.transactions, sequence_number); - num_approvals_and_rejections_internal(&multisig_account_resource.owners, transaction) + let transaction = + table::borrow(&multisig_account_resource.transactions, sequence_number); + num_approvals_and_rejections_internal( + &multisig_account_resource.owners, transaction + ) } - inline fun has_voted_for_approval(multisig_account: address, sequence_number: u64, owner: address): bool acquires MultisigAccount { + inline fun has_voted_for_approval( + multisig_account: address, sequence_number: u64, owner: address + ): bool acquires MultisigAccount { let (voted, vote) = vote(multisig_account, sequence_number, owner); voted && vote } - inline fun has_voted_for_rejection(multisig_account: address, sequence_number: u64, owner: address): bool acquires MultisigAccount { + inline fun has_voted_for_rejection( + multisig_account: address, sequence_number: u64, owner: address + ): bool acquires MultisigAccount { let (voted, vote) = vote(multisig_account, sequence_number, owner); voted && !vote } inline fun assert_multisig_account_exists(multisig_account: address) { - assert!(exists(multisig_account), error::invalid_state(EACCOUNT_NOT_MULTISIG)); + assert!( + exists(multisig_account), + error::invalid_state(EACCOUNT_NOT_MULTISIG) + ); } - inline fun assert_valid_sequence_number(multisig_account: address, sequence_number: u64) acquires MultisigAccount { + inline fun assert_valid_sequence_number( + multisig_account: address, sequence_number: u64 + ) acquires MultisigAccount { let multisig_account_resource = borrow_global(multisig_account); assert!( - sequence_number > 0 && sequence_number < multisig_account_resource.next_sequence_number, - error::invalid_argument(EINVALID_SEQUENCE_NUMBER), + sequence_number > 0 + && sequence_number < multisig_account_resource.next_sequence_number, + error::invalid_argument(EINVALID_SEQUENCE_NUMBER) ); } - inline fun assert_transaction_exists(multisig_account: address, sequence_number: u64) acquires MultisigAccount { + inline fun assert_transaction_exists( + multisig_account: address, sequence_number: u64 + ) acquires MultisigAccount { let multisig_account_resource = borrow_global(multisig_account); assert!( table::contains(&multisig_account_resource.transactions, sequence_number), - error::not_found(ETRANSACTION_NOT_FOUND), + error::not_found(ETRANSACTION_NOT_FOUND) ); } @@ -1438,18 +1617,21 @@ module supra_framework::multisig_account { multisig_address: address, new_owners: vector
, owners_to_remove: vector
, - optional_new_num_signatures_required: Option, + optional_new_num_signatures_required: Option ) acquires MultisigAccount { assert_multisig_account_exists(multisig_address); let multisig_account_ref_mut = borrow_global_mut(multisig_address); // Verify no overlap between new owners and owners to remove. - vector::for_each_ref(&new_owners, |new_owner_ref| { - assert!( - !vector::contains(&owners_to_remove, new_owner_ref), - error::invalid_argument(EOWNERS_TO_REMOVE_NEW_OWNERS_OVERLAP) - ) - }); + vector::for_each_ref( + &new_owners, + |new_owner_ref| { + assert!( + !vector::contains(&owners_to_remove, new_owner_ref), + error::invalid_argument(EOWNERS_TO_REMOVE_NEW_OWNERS_OVERLAP) + ) + } + ); // If new owners provided, try to add them and emit an event. if (vector::length(&new_owners) > 0) { vector::append(&mut multisig_account_ref_mut.owners, new_owners); @@ -1458,7 +1640,12 @@ module supra_framework::multisig_account { multisig_address ); if (std::features::module_event_migration_enabled()) { - emit(AddOwners { multisig_account: multisig_address, owners_added: new_owners }); + emit( + AddOwners { + multisig_account: multisig_address, + owners_added: new_owners + } + ); }; emit_event( &mut multisig_account_ref_mut.add_owners_events, @@ -1469,16 +1656,20 @@ module supra_framework::multisig_account { if (vector::length(&owners_to_remove) > 0) { let owners_ref_mut = &mut multisig_account_ref_mut.owners; let owners_removed = vector[]; - vector::for_each_ref(&owners_to_remove, |owner_to_remove_ref| { - let (found, index) = - vector::index_of(owners_ref_mut, owner_to_remove_ref); - if (found) { - vector::push_back( - &mut owners_removed, - vector::swap_remove(owners_ref_mut, index) + vector::for_each_ref( + &owners_to_remove, + |owner_to_remove_ref| { + let (found, index) = vector::index_of( + owners_ref_mut, owner_to_remove_ref ); + if (found) { + vector::push_back( + &mut owners_removed, + vector::swap_remove(owners_ref_mut, index) + ); + } } - }); + ); // Only emit event if owner(s) actually removed. if (vector::length(&owners_removed) > 0) { if (std::features::module_event_migration_enabled()) { @@ -1504,14 +1695,13 @@ module supra_framework::multisig_account { multisig_account_ref_mut.num_signatures_required; // Only apply update and emit event if a change indicated. if (new_num_signatures_required != old_num_signatures_required) { - multisig_account_ref_mut.num_signatures_required = - new_num_signatures_required; + multisig_account_ref_mut.num_signatures_required = new_num_signatures_required; if (std::features::module_event_migration_enabled()) { emit( UpdateSignaturesRequired { multisig_account: multisig_address, old_num_signatures_required, - new_num_signatures_required, + new_num_signatures_required } ); }; @@ -1519,7 +1709,7 @@ module supra_framework::multisig_account { &mut multisig_account_ref_mut.update_signature_required_events, UpdateSignaturesRequiredEvent { old_num_signatures_required, - new_num_signatures_required, + new_num_signatures_required } ); } @@ -1566,7 +1756,7 @@ module supra_framework::multisig_account { ExecutionError { abort_location: utf8(ABORT_LOCATION), error_type: utf8(ERROR_TYPE), - error_code: ERROR_CODE, + error_code: ERROR_CODE } } @@ -1574,7 +1764,14 @@ module supra_framework::multisig_account { fun setup() { let framework_signer = &create_signer(@0x1); features::change_feature_flags_for_testing( - framework_signer, vector[features::get_multisig_accounts_feature(), features::get_multisig_v2_enhancement_feature(), features::get_abort_if_multisig_payload_mismatch_feature()], vector[]); + framework_signer, + vector[ + features::get_multisig_accounts_feature(), + features::get_multisig_v2_enhancement_feature(), + features::get_abort_if_multisig_payload_mismatch_feature() + ], + vector[] + ); timestamp::set_time_has_started_for_testing(framework_signer); chain_id::initialize_for_test(framework_signer, 1); let (burn, mint) = supra_coin::initialize_for_test(framework_signer); @@ -1586,7 +1783,10 @@ module supra_framework::multisig_account { fun setup_disabled() { let framework_signer = &create_signer(@0x1); features::change_feature_flags_for_testing( - framework_signer, vector[], vector[features::get_multisig_accounts_feature()]); + framework_signer, + vector[], + vector[features::get_multisig_accounts_feature()] + ); timestamp::set_time_has_started_for_testing(framework_signer); chain_id::initialize_for_test(framework_signer, 1); let (burn, mint) = supra_coin::initialize_for_test(framework_signer); @@ -1608,24 +1808,36 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_end_to_end( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); // Create three transactions. create_transaction(owner_1, multisig_account, PAYLOAD); create_transaction(owner_2, multisig_account, PAYLOAD); create_transaction_with_hash(owner_3, multisig_account, sha3_256(PAYLOAD)); - assert!(get_pending_transactions(multisig_account) == vector[ - get_transaction(multisig_account, 1), - get_transaction(multisig_account, 2), - get_transaction(multisig_account, 3), - ], 0); + assert!( + get_pending_transactions(multisig_account) + == vector[ + get_transaction(multisig_account, 1), + get_transaction(multisig_account, 2), + get_transaction(multisig_account, 3) + ], + 0 + ); // Owner 3 doesn't need to explicitly approve as they created the transaction. approve_transaction(owner_1, multisig_account, 3); @@ -1638,41 +1850,59 @@ module supra_framework::multisig_account { assert!(can_be_executed(multisig_account, 1), 1); // First transaction was executed successfully. successful_transaction_execution_cleanup(owner_2_addr, multisig_account, vector[]); - assert!(get_pending_transactions(multisig_account) == vector[ - get_transaction(multisig_account, 2), - get_transaction(multisig_account, 3), - ], 0); + assert!( + get_pending_transactions(multisig_account) + == vector[ + get_transaction(multisig_account, 2), + get_transaction(multisig_account, 3) + ], + 0 + ); reject_transaction(owner_1, multisig_account, 2); reject_transaction(owner_3, multisig_account, 2); // Second transaction has 1 approval (owner 3) and 2 rejections (owners 1 & 2) and thus can be removed. assert!(can_be_rejected(multisig_account, 2), 2); execute_rejected_transaction(owner_1, multisig_account); - assert!(get_pending_transactions(multisig_account) == vector[ - get_transaction(multisig_account, 3), - ], 0); + assert!( + get_pending_transactions(multisig_account) + == vector[get_transaction(multisig_account, 3)], + 0 + ); // Third transaction can be executed now but execution fails. - failed_transaction_execution_cleanup(owner_3_addr, multisig_account, PAYLOAD, execution_error()); + failed_transaction_execution_cleanup( + owner_3_addr, multisig_account, PAYLOAD, execution_error() + ); assert!(get_pending_transactions(multisig_account) == vector[], 0); } #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_end_to_end_customization( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); // Create one transactions. create_transaction(owner_1, multisig_account, PAYLOAD); - assert!(get_pending_transactions(multisig_account) == vector[ - get_transaction(multisig_account, 1), - ], 0); + assert!( + get_pending_transactions(multisig_account) + == vector[get_transaction(multisig_account, 1)], + 0 + ); // Owner 1 doesn't need to explicitly approve as they created the transaction. approve_transaction(owner_2, multisig_account, 1); @@ -1696,11 +1926,19 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_create_with_as_many_sigs_required_as_num_owners( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); create_account(owner_1_addr); - create_with_owners(owner_1, vector[address_of(owner_2), address_of(owner_3)], 3, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[address_of(owner_2), address_of(owner_3)], + 3, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); let multisig_account = get_next_multisig_account_address(owner_1_addr); assert_multisig_account_exists(multisig_account); } @@ -1708,7 +1946,8 @@ module supra_framework::multisig_account { #[test(owner = @0x123)] #[expected_failure(abort_code = 0x1000B, location = Self)] public entry fun test_create_with_zero_signatures_required_should_fail( - owner: &signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); create(owner, 0, vector[], vector[], MINIMAL_TIMEOUT_DURATION); @@ -1717,7 +1956,8 @@ module supra_framework::multisig_account { #[test(owner = @0x123)] #[expected_failure(abort_code = 0x1000B, location = Self)] public entry fun test_create_with_too_many_signatures_required_should_fail( - owner: &signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); create(owner, 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); @@ -1726,7 +1966,8 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] #[expected_failure(abort_code = 0x10001, location = Self)] public entry fun test_create_with_duplicate_owners_should_fail( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner_1)); create_with_owners( @@ -1735,18 +1976,20 @@ module supra_framework::multisig_account { // Duplicate owner 2 addresses. address_of(owner_2), address_of(owner_3), - address_of(owner_2), + address_of(owner_2) ], 2, vector[], vector[], - MINIMAL_TIMEOUT_DURATION,); + MINIMAL_TIMEOUT_DURATION + ); } #[test(owner = @0x123)] #[expected_failure(abort_code = 0xD000E, location = Self)] public entry fun test_create_with_without_feature_flag_enabled_should_fail( - owner: &signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup_disabled(); create_account(address_of(owner)); create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); @@ -1755,28 +1998,32 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] #[expected_failure(abort_code = 0x10001, location = Self)] public entry fun test_create_with_creator_in_additional_owners_list_should_fail( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner_1)); - create_with_owners(owner_1, vector[ - // Duplicate owner 1 addresses. - address_of(owner_1), - address_of(owner_2), - address_of(owner_3), - ], 2, + create_with_owners( + owner_1, + vector[ + // Duplicate owner 1 addresses. + address_of(owner_1), + address_of(owner_2), + address_of(owner_3) + ], + 2, vector[], vector[], - MINIMAL_TIMEOUT_DURATION, + MINIMAL_TIMEOUT_DURATION ); } #[test] - public entry fun test_create_multisig_account_on_top_of_existing_multi_ed25519_account() - acquires MultisigAccount { + public entry fun test_create_multisig_account_on_top_of_existing_multi_ed25519_account() acquires MultisigAccount { setup(); let (curr_sk, curr_pk) = multi_ed25519::generate_keys(2, 3); let pk_unvalidated = multi_ed25519::public_key_to_unvalidated(&curr_pk); - let auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&pk_unvalidated); + let auth_key = + multi_ed25519::unvalidated_public_key_to_authentication_key(&pk_unvalidated); let multisig_address = from_bcs::to_address(auth_key); create_account(multisig_address); @@ -1786,7 +2033,7 @@ module supra_framework::multisig_account { account_address: multisig_address, sequence_number: account::get_sequence_number(multisig_address), owners: expected_owners, - num_signatures_required: 2, + num_signatures_required: 2 }; let signed_proof = multi_ed25519::sign_struct(&curr_sk, proof); create_with_existing_account( @@ -1798,19 +2045,19 @@ module supra_framework::multisig_account { multi_ed25519::signature_to_bytes(&signed_proof), vector[], vector[], - MINIMAL_TIMEOUT_DURATION, + MINIMAL_TIMEOUT_DURATION ); assert_multisig_account_exists(multisig_address); assert!(owners(multisig_address) == expected_owners, 0); } #[test] - public entry fun test_create_multisig_account_on_top_of_existing_multi_ed25519_account_and_revoke_auth_key() - acquires MultisigAccount { + public entry fun test_create_multisig_account_on_top_of_existing_multi_ed25519_account_and_revoke_auth_key() acquires MultisigAccount { setup(); let (curr_sk, curr_pk) = multi_ed25519::generate_keys(2, 3); let pk_unvalidated = multi_ed25519::public_key_to_unvalidated(&curr_pk); - let auth_key = multi_ed25519::unvalidated_public_key_to_authentication_key(&pk_unvalidated); + let auth_key = + multi_ed25519::unvalidated_public_key_to_authentication_key(&pk_unvalidated); let multisig_address = from_bcs::to_address(auth_key); create_account(multisig_address); @@ -1824,7 +2071,7 @@ module supra_framework::multisig_account { account_address: multisig_address, sequence_number: account::get_sequence_number(multisig_address), owners: expected_owners, - num_signatures_required: 2, + num_signatures_required: 2 }; let signed_proof = multi_ed25519::sign_struct(&curr_sk, proof); create_with_existing_account_and_revoke_auth_key( @@ -1836,7 +2083,7 @@ module supra_framework::multisig_account { multi_ed25519::signature_to_bytes(&signed_proof), vector[], vector[], - MINIMAL_TIMEOUT_DURATION, + MINIMAL_TIMEOUT_DURATION ); assert_multisig_account_exists(multisig_address); assert!(owners(multisig_address) == expected_owners, 0); @@ -1848,11 +2095,19 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_update_signatures_required( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); create_account(owner_1_addr); - create_with_owners(owner_1, vector[address_of(owner_2), address_of(owner_3)], 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[address_of(owner_2), address_of(owner_3)], + 1, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); let multisig_account = get_next_multisig_account_address(owner_1_addr); assert!(num_signatures_required(multisig_account) == 1, 0); update_signatures_required(&create_signer(multisig_account), 2); @@ -1867,12 +2122,12 @@ module supra_framework::multisig_account { setup(); let owner_addr = address_of(owner); create_account(owner_addr); - create(owner,1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); let multisig_account = get_next_multisig_account_address(owner_addr); update_metadata( &create_signer(multisig_account), vector[utf8(b"key1"), utf8(b"key2")], - vector[vector[1], vector[2]], + vector[vector[1], vector[2]] ); let updated_metadata = metadata(multisig_account); assert!(simple_map::length(&updated_metadata) == 2, 0); @@ -1885,7 +2140,7 @@ module supra_framework::multisig_account { setup(); let owner_addr = address_of(owner); create_account(owner_addr); - create(owner,1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); let multisig_account = get_next_multisig_account_address(owner_addr); update_timeout_duration(&create_signer(multisig_account), 1000); let updated_timeout = timeout_duration(multisig_account); @@ -1895,10 +2150,11 @@ module supra_framework::multisig_account { #[test(owner = @0x123)] #[expected_failure(abort_code = 0x1000B, location = Self)] public entry fun test_update_with_zero_signatures_required_should_fail( - owner: & signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); let multisig_account = get_next_multisig_account_address(address_of(owner)); update_signatures_required(&create_signer(multisig_account), 0); } @@ -1906,17 +2162,19 @@ module supra_framework::multisig_account { #[test(owner = @0x123)] #[expected_failure(abort_code = 0x30005, location = Self)] public entry fun test_update_with_too_many_signatures_required_should_fail( - owner: &signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); let multisig_account = get_next_multisig_account_address(address_of(owner)); update_signatures_required(&create_signer(multisig_account), 2); } #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_add_owners( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner_1)); create(owner_1, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); @@ -1930,24 +2188,44 @@ module supra_framework::multisig_account { add_owners(multisig_signer, vector[]); assert!(owners(multisig_account) == vector[owner_1_addr], 1); add_owners(multisig_signer, vector[owner_2_addr, owner_3_addr]); - assert!(owners(multisig_account) == vector[owner_1_addr, owner_2_addr, owner_3_addr], 2); + assert!( + owners(multisig_account) + == vector[owner_1_addr, owner_2_addr, owner_3_addr], + 2 + ); } #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_remove_owners( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 1, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); let multisig_account = get_next_multisig_account_address(owner_1_addr); let multisig_signer = &create_signer(multisig_account); - assert!(owners(multisig_account) == vector[owner_2_addr, owner_3_addr, owner_1_addr], 0); + assert!( + owners(multisig_account) + == vector[owner_2_addr, owner_3_addr, owner_1_addr], + 0 + ); // Removing an empty vector of owners should be no-op. remove_owners(multisig_signer, vector[]); - assert!(owners(multisig_account) == vector[owner_2_addr, owner_3_addr, owner_1_addr], 1); + assert!( + owners(multisig_account) + == vector[owner_2_addr, owner_3_addr, owner_1_addr], + 1 + ); remove_owners(multisig_signer, vector[owner_2_addr]); assert!(owners(multisig_account) == vector[owner_1_addr, owner_3_addr], 2); // Removing owners that don't exist should be no-op. @@ -1961,15 +2239,27 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] #[expected_failure(abort_code = 0x30005, location = Self)] public entry fun test_remove_all_owners_should_fail( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 1, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); let multisig_account = get_next_multisig_account_address(owner_1_addr); - assert!(owners(multisig_account) == vector[owner_2_addr, owner_3_addr, owner_1_addr], 0); + assert!( + owners(multisig_account) + == vector[owner_2_addr, owner_3_addr, owner_1_addr], + 0 + ); let multisig_signer = &create_signer(multisig_account); remove_owners(multisig_signer, vector[owner_1_addr, owner_2_addr, owner_3_addr]); } @@ -1977,13 +2267,21 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] #[expected_failure(abort_code = 0x30005, location = Self)] public entry fun test_remove_owners_with_fewer_remaining_than_signature_threshold_should_fail( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); let multisig_account = get_next_multisig_account_address(owner_1_addr); let multisig_signer = &create_signer(multisig_account); // Remove 2 owners so there's one left, which is less than the signature threshold of 2. @@ -1992,14 +2290,22 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_create_transaction( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); create_transaction(owner_1, multisig_account, PAYLOAD); let transaction = get_transaction(multisig_account, 1); @@ -2016,10 +2322,11 @@ module supra_framework::multisig_account { #[test(owner = @0x123)] #[expected_failure(abort_code = 0x10004, location = Self)] public entry fun test_create_transaction_with_empty_payload_should_fail( - owner: &signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); let multisig_account = get_next_multisig_account_address(address_of(owner)); create_transaction(owner, multisig_account, vector[]); } @@ -2027,20 +2334,20 @@ module supra_framework::multisig_account { #[test(owner = @0x123, non_owner = @0x124)] #[expected_failure(abort_code = 0x507D3, location = Self)] public entry fun test_create_transaction_with_non_owner_should_fail( - owner: &signer, non_owner: &signer) acquires MultisigAccount { + owner: &signer, non_owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); let multisig_account = get_next_multisig_account_address(address_of(owner)); create_transaction(non_owner, multisig_account, PAYLOAD); } #[test(owner = @0x123)] - public entry fun test_create_transaction_with_hashes( - owner: &signer) acquires MultisigAccount { + public entry fun test_create_transaction_with_hashes(owner: &signer) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); let multisig_account = get_next_multisig_account_address(address_of(owner)); create_transaction_with_hash(owner, multisig_account, sha3_256(PAYLOAD)); } @@ -2048,10 +2355,11 @@ module supra_framework::multisig_account { #[test(owner = @0x123)] #[expected_failure(abort_code = 0x1000C, location = Self)] public entry fun test_create_transaction_with_empty_hash_should_fail( - owner: &signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); let multisig_account = get_next_multisig_account_address(address_of(owner)); create_transaction_with_hash(owner, multisig_account, vector[]); } @@ -2059,24 +2367,33 @@ module supra_framework::multisig_account { #[test(owner = @0x123, non_owner = @0x124)] #[expected_failure(abort_code = 0x507D3, location = Self)] public entry fun test_create_transaction_with_hashes_and_non_owner_should_fail( - owner: &signer, non_owner: &signer) acquires MultisigAccount { + owner: &signer, non_owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); - create(owner,1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); let multisig_account = get_next_multisig_account_address(address_of(owner)); create_transaction_with_hash(non_owner, multisig_account, sha3_256(PAYLOAD)); } #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_approve_transaction( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); create_transaction(owner_1, multisig_account, PAYLOAD); approve_transaction(owner_2, multisig_account, 1); @@ -2090,14 +2407,22 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_validate_transaction_should_not_consider_removed_owners( - owner_1: &signer, owner_2: &signer, owner_3: & signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); // Owner 1 and 2 approved but then owner 1 got removed. create_transaction(owner_1, multisig_account, PAYLOAD); @@ -2114,7 +2439,8 @@ module supra_framework::multisig_account { #[test(owner = @0x123)] #[expected_failure(abort_code = 0x607D6, location = Self)] public entry fun test_approve_transaction_with_invalid_sequence_number_should_fail( - owner: &signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); let multisig_account = get_next_multisig_account_address(address_of(owner)); @@ -2127,7 +2453,8 @@ module supra_framework::multisig_account { #[test(owner = @0x123, non_owner = @0x124)] #[expected_failure(abort_code = 0x507D3, location = Self)] public entry fun test_approve_transaction_with_non_owner_should_fail( - owner: &signer, non_owner: &signer) acquires MultisigAccount { + owner: &signer, non_owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); let multisig_account = get_next_multisig_account_address(address_of(owner)); @@ -2139,7 +2466,8 @@ module supra_framework::multisig_account { #[test(owner = @0x123)] public entry fun test_approval_transaction_after_rejecting( - owner: &signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup(); let owner_addr = address_of(owner); create_account(owner_addr); @@ -2155,14 +2483,22 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_reject_transaction( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); create_transaction(owner_1, multisig_account, PAYLOAD); reject_transaction(owner_1, multisig_account, 1); @@ -2177,7 +2513,8 @@ module supra_framework::multisig_account { #[test(owner = @0x123)] public entry fun test_reject_transaction_after_approving( - owner: &signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup(); let owner_addr = address_of(owner); create_account(owner_addr); @@ -2193,7 +2530,8 @@ module supra_framework::multisig_account { #[test(owner = @0x123)] #[expected_failure(abort_code = 0x607D6, location = Self)] public entry fun test_reject_transaction_with_invalid_sequence_number_should_fail( - owner: &signer) acquires MultisigAccount { + owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); let multisig_account = get_next_multisig_account_address(address_of(owner)); @@ -2206,7 +2544,8 @@ module supra_framework::multisig_account { #[test(owner = @0x123, non_owner = @0x124)] #[expected_failure(abort_code = 0x507D3, location = Self)] public entry fun test_reject_transaction_with_non_owner_should_fail( - owner: &signer, non_owner: &signer) acquires MultisigAccount { + owner: &signer, non_owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); let multisig_account = get_next_multisig_account_address(address_of(owner)); @@ -2216,88 +2555,143 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_execute_transaction_successful( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); create_transaction(owner_1, multisig_account, PAYLOAD); // Owner 1 doesn't need to explicitly approve as they created the transaction. approve_transaction(owner_2, multisig_account, 1); assert!(can_be_executed(multisig_account, 1), 1); - assert!(table::contains(&borrow_global(multisig_account).transactions, 1), 0); + assert!( + table::contains( + &borrow_global(multisig_account).transactions, 1 + ), + 0 + ); successful_transaction_execution_cleanup(owner_3_addr, multisig_account, vector[]); } #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_execute_transaction_failed( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); create_transaction(owner_1, multisig_account, PAYLOAD); // Owner 1 doesn't need to explicitly approve as they created the transaction. approve_transaction(owner_2, multisig_account, 1); assert!(can_be_executed(multisig_account, 1), 1); - assert!(table::contains(&borrow_global(multisig_account).transactions, 1), 0); - failed_transaction_execution_cleanup(owner_3_addr, multisig_account, vector[], execution_error()); + assert!( + table::contains( + &borrow_global(multisig_account).transactions, 1 + ), + 0 + ); + failed_transaction_execution_cleanup( + owner_3_addr, multisig_account, vector[], execution_error() + ); } #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_execute_transaction_with_full_payload( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); create_transaction_with_hash(owner_3, multisig_account, sha3_256(PAYLOAD)); // Owner 3 doesn't need to explicitly approve as they created the transaction. approve_transaction(owner_1, multisig_account, 1); assert!(can_be_executed(multisig_account, 1), 1); - assert!(table::contains(&borrow_global(multisig_account).transactions, 1), 0); + assert!( + table::contains( + &borrow_global(multisig_account).transactions, 1 + ), + 0 + ); successful_transaction_execution_cleanup(owner_3_addr, multisig_account, PAYLOAD); } #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_execute_rejected_transaction( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); create_transaction(owner_1, multisig_account, PAYLOAD); reject_transaction(owner_2, multisig_account, 1); reject_transaction(owner_3, multisig_account, 1); assert!(can_be_rejected(multisig_account, 1), 1); - assert!(table::contains(&borrow_global(multisig_account).transactions, 1), 0); + assert!( + table::contains( + &borrow_global(multisig_account).transactions, 1 + ), + 0 + ); execute_rejected_transaction(owner_3, multisig_account); } #[test(owner = @0x123, non_owner = @0x124)] #[expected_failure(abort_code = 0x507D3, location = Self)] public entry fun test_execute_rejected_transaction_with_non_owner_should_fail( - owner: &signer, non_owner: &signer) acquires MultisigAccount { + owner: &signer, non_owner: &signer + ) acquires MultisigAccount { setup(); create_account(address_of(owner)); let multisig_account = get_next_multisig_account_address(address_of(owner)); - create(owner,1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create(owner, 1, vector[], vector[], MINIMAL_TIMEOUT_DURATION); create_transaction(owner, multisig_account, PAYLOAD); reject_transaction(owner, multisig_account, 1); @@ -2307,14 +2701,22 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] #[expected_failure(abort_code = 0x3000A, location = Self)] public entry fun test_execute_rejected_transaction_without_sufficient_rejections_should_fail( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); create_transaction(owner_1, multisig_account, PAYLOAD); execute_rejected_transaction(owner_3, multisig_account); @@ -2322,30 +2724,32 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] public entry fun test_execute_rejected_transaction_timeout_should_success( - owner_1: &signer, owner_2: &signer, owner_3: &signer) acquires MultisigAccount { + owner_1: &signer, owner_2: &signer, owner_3: &signer + ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); let owner_2_addr = address_of(owner_2); let owner_3_addr = address_of(owner_3); create_account(owner_1_addr); let multisig_account = get_next_multisig_account_address(owner_1_addr); - create_with_owners(owner_1, vector[owner_2_addr, owner_3_addr], 2, vector[], vector[], MINIMAL_TIMEOUT_DURATION); + create_with_owners( + owner_1, + vector[owner_2_addr, owner_3_addr], + 2, + vector[], + vector[], + MINIMAL_TIMEOUT_DURATION + ); create_transaction(owner_1, multisig_account, PAYLOAD); - fast_forward_seconds(MINIMAL_TIMEOUT_DURATION+1); + fast_forward_seconds(MINIMAL_TIMEOUT_DURATION + 1); execute_rejected_transaction(owner_3, multisig_account); } - #[test( - owner_1 = @0x123, - owner_2 = @0x124, - owner_3 = @0x125 - )] + #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] #[expected_failure(abort_code = 0x10012, location = Self)] fun test_update_owner_schema_overlap_should_fail( - owner_1: &signer, - owner_2: &signer, - owner_3: &signer + owner_1: &signer, owner_2: &signer, owner_3: &signer ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); @@ -2372,9 +2776,7 @@ module supra_framework::multisig_account { #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] #[expected_failure(abort_code = 196627, location = Self)] fun test_max_pending_transaction_limit_should_fail( - owner_1: &signer, - owner_2: &signer, - owner_3: &signer + owner_1: &signer, owner_2: &signer, owner_3: &signer ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); @@ -2402,9 +2804,9 @@ module supra_framework::multisig_account { fun create_transaction_with_eviction( owner: &signer, multisig_account: address, - payload: vector, + payload: vector ) acquires MultisigAccount { - while(available_transaction_queue_capacity(multisig_account) == 0) { + while (available_transaction_queue_capacity(multisig_account) == 0) { execute_rejected_transaction(owner, multisig_account) }; create_transaction(owner, multisig_account, payload); @@ -2412,17 +2814,23 @@ module supra_framework::multisig_account { #[test_only] fun vote_all_transactions( - owner: &signer, multisig_account: address, approved: bool) acquires MultisigAccount { - let starting_sequence_number = last_resolved_sequence_number(multisig_account) + 1; + owner: &signer, multisig_account: address, approved: bool + ) acquires MultisigAccount { + let starting_sequence_number = last_resolved_sequence_number(multisig_account) + + 1; let final_sequence_number = next_sequence_number(multisig_account) - 1; - vote_transactions(owner, multisig_account, starting_sequence_number, final_sequence_number, approved); + vote_transactions( + owner, + multisig_account, + starting_sequence_number, + final_sequence_number, + approved + ); } #[test(owner_1 = @0x123, owner_2 = @0x124, owner_3 = @0x125)] fun test_dos_mitigation_end_to_end( - owner_1: &signer, - owner_2: &signer, - owner_3: &signer + owner_1: &signer, owner_2: &signer, owner_3: &signer ) acquires MultisigAccount { setup(); let owner_1_addr = address_of(owner_1); @@ -2470,8 +2878,7 @@ module supra_framework::multisig_account { #[test(owner = @0x123, non_owner = @0x234)] #[expected_failure(abort_code = 329683, location = Self)] public entry fun test_create_transaction_should_fail_if_not_owner( - owner: &signer, - non_owner: &signer + owner: &signer, non_owner: &signer ) acquires MultisigAccount { setup(); create_account(address_of(owner)); @@ -2484,8 +2891,7 @@ module supra_framework::multisig_account { #[test(owner = @0x123, non_owner = @0x234)] #[expected_failure(abort_code = 329683, location = Self)] public entry fun test_create_transaction_with_hash_should_fail_if_not_owner( - owner: &signer, - non_owner: &signer + owner: &signer, non_owner: &signer ) acquires MultisigAccount { setup(); create_account(address_of(owner)); @@ -2498,8 +2904,7 @@ module supra_framework::multisig_account { #[test(owner = @0x123, non_owner = @0x234)] #[expected_failure(abort_code = 329683, location = Self)] public entry fun test_reject_transaction_should_fail_if_not_owner( - owner: &signer, - non_owner: &signer + owner: &signer, non_owner: &signer ) acquires MultisigAccount { setup(); create_account(address_of(owner)); @@ -2510,12 +2915,10 @@ module supra_framework::multisig_account { reject_transaction(non_owner, multisig_account, 1); } - #[test(owner = @0x123, non_owner = @0x234)] #[expected_failure(abort_code = 329683, location = Self)] public entry fun test_approve_transaction_should_fail_if_not_owner( - owner: &signer, - non_owner: &signer + owner: &signer, non_owner: &signer ) acquires MultisigAccount { setup(); create_account(address_of(owner)); @@ -2529,8 +2932,7 @@ module supra_framework::multisig_account { #[test(owner = @0x123, non_owner = @0x234)] #[expected_failure(abort_code = 329683, location = Self)] public entry fun test_vote_transaction_should_fail_if_not_owner( - owner: &signer, - non_owner: &signer + owner: &signer, non_owner: &signer ) acquires MultisigAccount { setup(); create_account(address_of(owner)); @@ -2544,8 +2946,7 @@ module supra_framework::multisig_account { #[test(owner = @0x123, non_owner = @0x234)] #[expected_failure(abort_code = 329683, location = Self)] public entry fun test_vote_transactions_should_fail_if_not_owner( - owner: &signer, - non_owner: &signer + owner: &signer, non_owner: &signer ) acquires MultisigAccount { setup(); create_account(address_of(owner)); @@ -2559,8 +2960,7 @@ module supra_framework::multisig_account { #[test(owner = @0x123, non_owner = @0x234)] #[expected_failure(abort_code = 329683, location = Self)] public entry fun test_execute_rejected_transaction_should_fail_if_not_owner( - owner: &signer, - non_owner: &signer + owner: &signer, non_owner: &signer ) acquires MultisigAccount { setup(); create_account(address_of(owner)); @@ -2572,12 +2972,10 @@ module supra_framework::multisig_account { execute_rejected_transaction(non_owner, multisig_account); } - #[test(owner = @0x123, non_owner = @0x234)] #[expected_failure(abort_code = 329683, location = Self)] public entry fun test_execute_rejected_transactions_should_fail_if_not_owner( - owner: &signer, - non_owner: &signer + owner: &signer, non_owner: &signer ) acquires MultisigAccount { setup(); create_account(address_of(owner)); diff --git a/aptos-move/framework/supra-framework/sources/multisig_account.spec.move b/aptos-move/framework/supra-framework/sources/multisig_account.spec.move index 18f347d919648..2020639942b7f 100644 --- a/aptos-move/framework/supra-framework/sources/multisig_account.spec.move +++ b/aptos-move/framework/supra-framework/sources/multisig_account.spec.move @@ -165,8 +165,7 @@ spec supra_framework::multisig_account { /// Enforcement: Audited that it aborts if the MultisigAccount doesn't exist on the account. /// - spec module { - } + spec module {} spec metadata(multisig_account: address): SimpleMap> { aborts_if !exists(multisig_account); @@ -175,7 +174,8 @@ spec supra_framework::multisig_account { spec num_signatures_required(multisig_account: address): u64 { aborts_if !exists(multisig_account); - ensures result == global(multisig_account).num_signatures_required; + ensures result + == global(multisig_account).num_signatures_required; } spec owners(multisig_account: address): vector
{ @@ -183,27 +183,32 @@ spec supra_framework::multisig_account { ensures result == global(multisig_account).owners; } - spec get_transaction( - multisig_account: address, - sequence_number: u64, - ): MultisigTransaction { + spec get_transaction(multisig_account: address, sequence_number: u64): MultisigTransaction { let multisig_account_resource = global(multisig_account); aborts_if !exists(multisig_account); - aborts_if sequence_number == 0 || sequence_number >= multisig_account_resource.next_sequence_number; - aborts_if !table::spec_contains(multisig_account_resource.transactions, sequence_number); - ensures result == table::spec_get(multisig_account_resource.transactions, sequence_number); + aborts_if sequence_number == 0 + || sequence_number >= multisig_account_resource.next_sequence_number; + aborts_if !table::spec_contains( + multisig_account_resource.transactions, sequence_number + ); + ensures result + == table::spec_get(multisig_account_resource.transactions, sequence_number); } - spec get_next_transaction_payload( - multisig_account: address, provided_payload: vector - ): vector { + spec get_next_transaction_payload(multisig_account: address, provided_payload: vector): vector { let multisig_account_resource = global(multisig_account); - let sequence_number = multisig_account_resource.last_executed_sequence_number + 1; - let transaction = table::spec_get(multisig_account_resource.transactions, sequence_number); + let sequence_number = multisig_account_resource.last_executed_sequence_number + + 1; + let transaction = table::spec_get( + multisig_account_resource.transactions, sequence_number + ); aborts_if !exists(multisig_account); aborts_if multisig_account_resource.last_executed_sequence_number + 1 > MAX_U64; - aborts_if !table::spec_contains(multisig_account_resource.transactions, sequence_number); - ensures option::spec_is_none(transaction.payload) ==> result == provided_payload; + aborts_if !table::spec_contains( + multisig_account_resource.transactions, sequence_number + ); + ensures option::spec_is_none(transaction.payload) ==> + result == provided_payload; } spec get_next_multisig_account_address(creator: address): address { @@ -223,21 +228,21 @@ spec supra_framework::multisig_account { ensures result == multisig_account_resource.next_sequence_number; } - spec vote( - multisig_account: address, - sequence_number: u64, - owner: address - ): (bool, bool) { + spec vote(multisig_account: address, sequence_number: u64, owner: address): (bool, bool) { let multisig_account_resource = global(multisig_account); aborts_if !exists(multisig_account); - aborts_if sequence_number == 0 || sequence_number >= multisig_account_resource.next_sequence_number; - aborts_if !table::spec_contains(multisig_account_resource.transactions, sequence_number); - let transaction = table::spec_get(multisig_account_resource.transactions, sequence_number); + aborts_if sequence_number == 0 + || sequence_number >= multisig_account_resource.next_sequence_number; + aborts_if !table::spec_contains( + multisig_account_resource.transactions, sequence_number + ); + let transaction = table::spec_get( + multisig_account_resource.transactions, sequence_number + ); let votes = transaction.votes; let voted = simple_map::spec_contains_key(votes, owner); let vote = voted && simple_map::spec_get(votes, owner); ensures result_1 == voted; ensures result_2 == vote; } - } diff --git a/aptos-move/framework/supra-framework/sources/multisig_voting.move b/aptos-move/framework/supra-framework/sources/multisig_voting.move index 5b49e5b944040..a5fc483f802aa 100644 --- a/aptos-move/framework/supra-framework/sources/multisig_voting.move +++ b/aptos-move/framework/supra-framework/sources/multisig_voting.move @@ -127,7 +127,7 @@ module supra_framework::multisig_voting { /// Whether the proposal has been resolved. is_resolved: bool, /// Resolution timestamp if the proposal has been resolved. 0 otherwise. - resolution_time_secs: u64, + resolution_time_secs: u64 } struct VotingForum has key { @@ -136,14 +136,14 @@ module supra_framework::multisig_voting { proposals: Table>, events: VotingEvents, /// Unique identifier for a proposal. This allows for 2 * 10**19 proposals. - next_proposal_id: u64, + next_proposal_id: u64 } struct VotingEvents has store { create_proposal_events: EventHandle, register_forum_events: EventHandle, resolve_proposal_events: EventHandle, - vote_events: EventHandle, + vote_events: EventHandle } #[event] @@ -152,20 +152,20 @@ module supra_framework::multisig_voting { execution_hash: vector, expiration_secs: u64, metadata: SimpleMap>, - min_vote_threshold: u64, + min_vote_threshold: u64 } #[event] struct RegisterForum has drop, store { hosting_account: address, - proposal_type_info: TypeInfo, + proposal_type_info: TypeInfo } #[event] struct Vote has drop, store { voter: address, proposal_id: u64, - is_vote_yes: bool, + is_vote_yes: bool } #[event] @@ -181,32 +181,41 @@ module supra_framework::multisig_voting { execution_hash: vector, expiration_secs: u64, metadata: SimpleMap>, - min_vote_threshold: u64, + min_vote_threshold: u64 } struct RegisterForumEvent has drop, store { hosting_account: address, - proposal_type_info: TypeInfo, + proposal_type_info: TypeInfo } struct VoteEvent has drop, store { voter: address, proposal_id: u64, - is_vote_yes: bool, + is_vote_yes: bool } public fun register(account: &signer) { let addr = signer::address_of(account); - assert!(!exists>(addr), error::already_exists(EVOTING_FORUM_ALREADY_REGISTERED)); + assert!( + !exists>(addr), + error::already_exists(EVOTING_FORUM_ALREADY_REGISTERED) + ); let voting_forum = VotingForum { next_proposal_id: 0, proposals: table::new>(), events: VotingEvents { - create_proposal_events: account::new_event_handle(account), - register_forum_events: account::new_event_handle(account), - resolve_proposal_events: account::new_event_handle(account), - vote_events: account::new_event_handle(account), + create_proposal_events: account::new_event_handle( + account + ), + register_forum_events: account::new_event_handle( + account + ), + resolve_proposal_events: account::new_event_handle( + account + ), + vote_events: account::new_event_handle(account) } }; @@ -214,16 +223,16 @@ module supra_framework::multisig_voting { event::emit( RegisterForum { hosting_account: addr, - proposal_type_info: type_info::type_of(), - }, + proposal_type_info: type_info::type_of() + } ); }; event::emit_event( &mut voting_forum.events.register_forum_events, RegisterForumEvent { hosting_account: addr, - proposal_type_info: type_info::type_of(), - }, + proposal_type_info: type_info::type_of() + } ); move_to(account, voting_forum); @@ -248,7 +257,7 @@ module supra_framework::multisig_voting { min_vote_threshold: u64, voters: vector
, expiration_secs: u64, - metadata: SimpleMap>, + metadata: SimpleMap> ): u64 acquires VotingForum { create_proposal_v2( proposer, @@ -285,51 +294,74 @@ module supra_framework::multisig_voting { voters: vector
, expiration_secs: u64, metadata: SimpleMap>, - is_multi_step_proposal: bool, + is_multi_step_proposal: bool ): u64 acquires VotingForum { // Make sure the execution script's hash is not empty. - assert!(vector::length(&execution_hash) > 0, error::invalid_argument(EPROPOSAL_EMPTY_EXECUTION_HASH)); + assert!( + vector::length(&execution_hash) > 0, + error::invalid_argument(EPROPOSAL_EMPTY_EXECUTION_HASH) + ); - assert!(min_vote_threshold > 1, error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE)); + assert!( + min_vote_threshold > 1, + error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE) + ); // Make sure voters length must greater or equal to vote threshold - assert!(vector::length(&voters) >= min_vote_threshold, error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS)); + assert!( + vector::length(&voters) >= min_vote_threshold, + error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS) + ); - let voting_forum = borrow_global_mut>(voting_forum_address); + let voting_forum = + borrow_global_mut>(voting_forum_address); let proposal_id = voting_forum.next_proposal_id; voting_forum.next_proposal_id = voting_forum.next_proposal_id + 1; // Add a flag to indicate if this proposal is single-step or multi-step. - simple_map::add(&mut metadata, utf8(IS_MULTI_STEP_PROPOSAL_KEY), to_bytes(&is_multi_step_proposal)); + simple_map::add( + &mut metadata, + utf8(IS_MULTI_STEP_PROPOSAL_KEY), + to_bytes(&is_multi_step_proposal) + ); - let is_multi_step_in_execution_key = utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); + let is_multi_step_in_execution_key = + utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); if (is_multi_step_proposal) { // If the given proposal is a multi-step proposal, we will add a flag to indicate if this multi-step proposal is in execution. // This value is by default false. We turn this value to true when we start executing the multi-step proposal. This value // will be used to disable further voting after we started executing the multi-step proposal. - simple_map::add(&mut metadata, is_multi_step_in_execution_key, to_bytes(&false)); + simple_map::add( + &mut metadata, is_multi_step_in_execution_key, to_bytes(&false) + ); // If the proposal is a single-step proposal, we check if the metadata passed by the client has the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY key. // If they have the key, we will remove it, because a single-step proposal that doesn't need this key. - } else if (simple_map::contains_key(&mut metadata, &is_multi_step_in_execution_key)) { + } else if (simple_map::contains_key( + &mut metadata, &is_multi_step_in_execution_key + )) { simple_map::remove(&mut metadata, &is_multi_step_in_execution_key); }; - table::add(&mut voting_forum.proposals, proposal_id, Proposal { - proposer, - creation_time_secs: timestamp::now_seconds(), - execution_content: option::some(execution_content), - execution_hash, - metadata, - min_vote_threshold, - voters, - expiration_secs, - yes_votes: 0, - no_votes: 0, - voted_records: table::new(), - is_resolved: false, - resolution_time_secs: 0, - }); + table::add( + &mut voting_forum.proposals, + proposal_id, + Proposal { + proposer, + creation_time_secs: timestamp::now_seconds(), + execution_content: option::some(execution_content), + execution_hash, + metadata, + min_vote_threshold, + voters, + expiration_secs, + yes_votes: 0, + no_votes: 0, + voted_records: table::new(), + is_resolved: false, + resolution_time_secs: 0 + } + ); if (std::features::module_event_migration_enabled()) { event::emit( @@ -338,8 +370,8 @@ module supra_framework::multisig_voting { execution_hash, expiration_secs, metadata, - min_vote_threshold, - }, + min_vote_threshold + } ); }; event::emit_event( @@ -349,8 +381,8 @@ module supra_framework::multisig_voting { execution_hash, expiration_secs, metadata, - min_vote_threshold, - }, + min_vote_threshold + } ); proposal_id @@ -368,31 +400,44 @@ module supra_framework::multisig_voting { _proof: &ProposalType, voting_forum_address: address, proposal_id: u64, - should_pass: bool, + should_pass: bool ) acquires VotingForum { let voter_address = signer::address_of(voter); - let voting_forum = borrow_global_mut>(voting_forum_address); + let voting_forum = + borrow_global_mut>(voting_forum_address); let proposal = table::borrow_mut(&mut voting_forum.proposals, proposal_id); - assert!(vector::contains(&proposal.voters, &voter_address), error::permission_denied(ENOT_MULTISIG_OWNER)); + assert!( + vector::contains(&proposal.voters, &voter_address), + error::permission_denied(ENOT_MULTISIG_OWNER) + ); // Voting might still be possible after the proposal has enough yes votes to be resolved early. This would only // lead to possible proposal resolution failure if the resolve early threshold is not definitive (e.g. < 50% + 1 // of the total voting token's supply). In this case, more voting might actually still be desirable. // Governance mechanisms built on this voting module can apply additional rules on when voting is closed as // appropriate. - assert!(!is_voting_period_over(proposal), error::invalid_state(EPROPOSAL_VOTING_ALREADY_ENDED)); + assert!( + !is_voting_period_over(proposal), + error::invalid_state(EPROPOSAL_VOTING_ALREADY_ENDED) + ); assert!(!proposal.is_resolved, error::invalid_state(EPROPOSAL_ALREADY_RESOLVED)); // Assert this proposal is single-step, or if the proposal is multi-step, it is not in execution yet. - assert!(!simple_map::contains_key(&proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY)) - || *simple_map::borrow(&proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY)) == to_bytes( - &false - ), - error::invalid_state(EMULTI_STEP_PROPOSAL_IN_EXECUTION)); + assert!( + !simple_map::contains_key( + &proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY) + ) || *simple_map::borrow( + &proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY) + ) == to_bytes(&false), + error::invalid_state(EMULTI_STEP_PROPOSAL_IN_EXECUTION) + ); if (table::contains(&proposal.voted_records, voter_address)) { - let voted_record = table::borrow_mut(&mut proposal.voted_records, voter_address); - assert!(voted_record != &should_pass, error::already_exists(EVOTE_DUPLICATE_VOTE)); + let voted_record = + table::borrow_mut(&mut proposal.voted_records, voter_address); + assert!( + voted_record != &should_pass, error::already_exists(EVOTE_DUPLICATE_VOTE) + ); *voted_record = should_pass; if (should_pass) { @@ -406,7 +451,11 @@ module supra_framework::multisig_voting { }; } else { // vote cannot be more than `max_vote_number` - assert!(proposal.yes_votes + proposal.no_votes < vector::length(&proposal.voters), error::invalid_state(EVOTE_OVERFLOW)); + assert!( + proposal.yes_votes + proposal.no_votes + < vector::length(&proposal.voters), + error::invalid_state(EVOTE_OVERFLOW) + ); if (should_pass) { proposal.yes_votes = proposal.yes_votes + 1; @@ -422,34 +471,48 @@ module supra_framework::multisig_voting { simple_map::upsert(&mut proposal.metadata, key, timestamp_secs_bytes); if (std::features::module_event_migration_enabled()) { - event::emit(Vote { proposal_id, is_vote_yes: should_pass, voter: voter_address }); + event::emit( + Vote { proposal_id, is_vote_yes: should_pass, voter: voter_address } + ); }; event::emit_event( &mut voting_forum.events.vote_events, - VoteEvent { proposal_id, is_vote_yes: should_pass, voter: voter_address }, + VoteEvent { proposal_id, is_vote_yes: should_pass, voter: voter_address } ); } /// Common checks on if a proposal is resolvable, regardless if the proposal is single-step or multi-step. fun is_proposal_resolvable( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ) acquires VotingForum { - let proposal_state = get_proposal_state(voting_forum_address, proposal_id); - assert!(proposal_state == PROPOSAL_STATE_SUCCEEDED, error::invalid_state(EPROPOSAL_CANNOT_BE_RESOLVED)); + let proposal_state = + get_proposal_state(voting_forum_address, proposal_id); + assert!( + proposal_state == PROPOSAL_STATE_SUCCEEDED, + error::invalid_state(EPROPOSAL_CANNOT_BE_RESOLVED) + ); - let voting_forum = borrow_global_mut>(voting_forum_address); + let voting_forum = + borrow_global_mut>(voting_forum_address); let proposal = table::borrow_mut(&mut voting_forum.proposals, proposal_id); assert!(!proposal.is_resolved, error::invalid_state(EPROPOSAL_ALREADY_RESOLVED)); // We need to make sure that the resolution is happening in // a separate transaction from the last vote to guard against any potential flashloan attacks. - let resolvable_time = to_u64(*simple_map::borrow(&proposal.metadata, &utf8(RESOLVABLE_TIME_METADATA_KEY))); - assert!(timestamp::now_seconds() > resolvable_time, error::invalid_state(ERESOLUTION_CANNOT_BE_ATOMIC)); + let resolvable_time = + to_u64( + *simple_map::borrow( + &proposal.metadata, &utf8(RESOLVABLE_TIME_METADATA_KEY) + ) + ); + assert!( + timestamp::now_seconds() > resolvable_time, + error::invalid_state(ERESOLUTION_CANNOT_BE_ATOMIC) + ); assert!( transaction_context::get_script_hash() == proposal.execution_hash, - error::invalid_argument(EPROPOSAL_EXECUTION_HASH_NOT_MATCHING), + error::invalid_argument(EPROPOSAL_EXECUTION_HASH_NOT_MATCHING) ); } @@ -459,22 +522,28 @@ module supra_framework::multisig_voting { /// @param voting_forum_address The address of the forum where the proposals are stored. /// @param proposal_id The proposal id. public fun resolve( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): ProposalType acquires VotingForum { is_proposal_resolvable(voting_forum_address, proposal_id); - let voting_forum = borrow_global_mut>(voting_forum_address); + let voting_forum = + borrow_global_mut>(voting_forum_address); let proposal = table::borrow_mut(&mut voting_forum.proposals, proposal_id); // Assert that the specified proposal is not a multi-step proposal. let multi_step_key = utf8(IS_MULTI_STEP_PROPOSAL_KEY); - let has_multi_step_key = simple_map::contains_key(&proposal.metadata, &multi_step_key); + let has_multi_step_key = + simple_map::contains_key(&proposal.metadata, &multi_step_key); if (has_multi_step_key) { - let is_multi_step_proposal = from_bcs::to_bool(*simple_map::borrow(&proposal.metadata, &multi_step_key)); + let is_multi_step_proposal = + from_bcs::to_bool( + *simple_map::borrow(&proposal.metadata, &multi_step_key) + ); assert!( !is_multi_step_proposal, - error::permission_denied(EMULTI_STEP_PROPOSAL_CANNOT_USE_SINGLE_STEP_RESOLVE_FUNCTION) + error::permission_denied( + EMULTI_STEP_PROPOSAL_CANNOT_USE_SINGLE_STEP_RESOLVE_FUNCTION + ) ); }; @@ -488,8 +557,8 @@ module supra_framework::multisig_voting { proposal_id, yes_votes: proposal.yes_votes, no_votes: proposal.no_votes, - resolved_early, - }, + resolved_early + } ); }; event::emit_event( @@ -498,8 +567,8 @@ module supra_framework::multisig_voting { proposal_id, yes_votes: proposal.yes_votes, no_votes: proposal.no_votes, - resolved_early, - }, + resolved_early + } ); option::extract(&mut proposal.execution_content) @@ -516,27 +585,31 @@ module supra_framework::multisig_voting { public fun resolve_proposal_v2( voting_forum_address: address, proposal_id: u64, - next_execution_hash: vector, + next_execution_hash: vector ) acquires VotingForum { is_proposal_resolvable(voting_forum_address, proposal_id); - let voting_forum = borrow_global_mut>(voting_forum_address); + let voting_forum = + borrow_global_mut>(voting_forum_address); let proposal = table::borrow_mut(&mut voting_forum.proposals, proposal_id); // Update the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY key to indicate that the multi-step proposal is in execution. let multi_step_in_execution_key = utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); if (simple_map::contains_key(&proposal.metadata, &multi_step_in_execution_key)) { - let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut( - &mut proposal.metadata, - &multi_step_in_execution_key - ); + let is_multi_step_proposal_in_execution_value = + simple_map::borrow_mut( + &mut proposal.metadata, + &multi_step_in_execution_key + ); *is_multi_step_proposal_in_execution_value = to_bytes(&true); }; let multi_step_key = utf8(IS_MULTI_STEP_PROPOSAL_KEY); - let is_multi_step = simple_map::contains_key(&proposal.metadata, &multi_step_key) && from_bcs::to_bool( - *simple_map::borrow(&proposal.metadata, &multi_step_key) - ); + let is_multi_step = + simple_map::contains_key(&proposal.metadata, &multi_step_key) + && from_bcs::to_bool( + *simple_map::borrow(&proposal.metadata, &multi_step_key) + ); let next_execution_hash_is_empty = vector::length(&next_execution_hash) == 0; // Assert that if this proposal is single-step, the `next_execution_hash` parameter is empty. @@ -555,10 +628,11 @@ module supra_framework::multisig_voting { // Set the `IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY` value to false upon successful resolution of the last step of a multi-step proposal. if (is_multi_step) { - let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut( - &mut proposal.metadata, - &multi_step_in_execution_key - ); + let is_multi_step_proposal_in_execution_value = + simple_map::borrow_mut( + &mut proposal.metadata, + &multi_step_in_execution_key + ); *is_multi_step_proposal_in_execution_value = to_bytes(&false); }; } else { @@ -577,8 +651,8 @@ module supra_framework::multisig_voting { proposal_id, yes_votes: proposal.yes_votes, no_votes: proposal.no_votes, - resolved_early, - }, + resolved_early + } ); }; event::emit_event( @@ -587,23 +661,24 @@ module supra_framework::multisig_voting { proposal_id, yes_votes: proposal.yes_votes, no_votes: proposal.no_votes, - resolved_early, - }, + resolved_early + } ); } #[view] /// Return the next unassigned proposal id - public fun next_proposal_id(voting_forum_address: address, ): u64 acquires VotingForum { + public fun next_proposal_id( + voting_forum_address: address + ): u64 acquires VotingForum { let voting_forum = borrow_global>(voting_forum_address); voting_forum.next_proposal_id } #[view] public fun get_proposer( - voting_forum_address: address, - proposal_id: u64 + voting_forum_address: address, proposal_id: u64 ): address acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.proposer @@ -611,16 +686,19 @@ module supra_framework::multisig_voting { #[view] public fun is_voting_closed( - voting_forum_address: address, - proposal_id: u64 + voting_forum_address: address, proposal_id: u64 ): bool acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); can_be_resolved_early(proposal) || is_voting_period_over(proposal) } /// Return true if the proposal has reached early resolution threshold (if specified). - public fun can_be_resolved_early(proposal: &Proposal): bool { - if (proposal.yes_votes >= proposal.min_vote_threshold || proposal.no_votes >= vector::length(&proposal.voters) - proposal.min_vote_threshold + 1) { + public fun can_be_resolved_early( + proposal: &Proposal + ): bool { + if (proposal.yes_votes >= proposal.min_vote_threshold + || proposal.no_votes + >= vector::length(&proposal.voters) - proposal.min_vote_threshold + 1) { return true }; false @@ -628,8 +706,7 @@ module supra_framework::multisig_voting { #[view] public fun get_proposal_metadata( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): SimpleMap> acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.metadata @@ -639,7 +716,7 @@ module supra_framework::multisig_voting { public fun get_proposal_metadata_value( voting_forum_address: address, proposal_id: u64, - metadata_key: String, + metadata_key: String ): vector acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); *simple_map::borrow(&proposal.metadata, &metadata_key) @@ -652,8 +729,7 @@ module supra_framework::multisig_voting { /// @param proposal_id The proposal id. /// @return Proposal state as an enum value. public fun get_proposal_state( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 acquires VotingForum { if (is_voting_closed(voting_forum_address, proposal_id)) { let proposal = get_proposal(voting_forum_address, proposal_id); @@ -670,8 +746,7 @@ module supra_framework::multisig_voting { #[view] /// Return the proposal's creation time. public fun get_proposal_creation_secs( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.creation_time_secs @@ -680,8 +755,7 @@ module supra_framework::multisig_voting { #[view] /// Return the proposal's expiration time. public fun get_proposal_expiration_secs( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.expiration_secs @@ -690,8 +764,7 @@ module supra_framework::multisig_voting { #[view] /// Return the proposal's execution hash. public fun get_execution_hash( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): vector acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.execution_hash @@ -700,8 +773,7 @@ module supra_framework::multisig_voting { #[view] /// Return the proposal's minimum vote threshold public fun get_min_vote_threshold( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.min_vote_threshold @@ -710,8 +782,7 @@ module supra_framework::multisig_voting { #[view] /// Return the proposal's current vote count (yes_votes, no_votes) public fun get_votes( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): (u64, u64) acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); (proposal.yes_votes, proposal.no_votes) @@ -720,8 +791,7 @@ module supra_framework::multisig_voting { #[view] /// Return true if the governance proposal has already been resolved. public fun is_resolved( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): bool acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.is_resolved @@ -729,8 +799,7 @@ module supra_framework::multisig_voting { #[view] public fun get_resolution_time_secs( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.resolution_time_secs @@ -739,27 +808,30 @@ module supra_framework::multisig_voting { #[view] /// Return true if the multi-step governance proposal is in execution. public fun is_multi_step_proposal_in_execution( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): bool acquires VotingForum { let voting_forum = borrow_global>(voting_forum_address); let proposal = table::borrow(&voting_forum.proposals, proposal_id); - let is_multi_step_in_execution_key = utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); + let is_multi_step_in_execution_key = + utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); assert!( simple_map::contains_key(&proposal.metadata, &is_multi_step_in_execution_key), error::invalid_argument(EPROPOSAL_IS_SINGLE_STEP) ); - from_bcs::to_bool(*simple_map::borrow(&proposal.metadata, &is_multi_step_in_execution_key)) + from_bcs::to_bool( + *simple_map::borrow(&proposal.metadata, &is_multi_step_in_execution_key) + ) } /// Return true if the voting period of the given proposal has already ended. - fun is_voting_period_over(proposal: &Proposal): bool { + fun is_voting_period_over( + proposal: &Proposal + ): bool { timestamp::now_seconds() > proposal.expiration_secs } inline fun get_proposal( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): &Proposal acquires VotingForum { let voting_forum = borrow_global>(voting_forum_address); table::borrow(&voting_forum.proposals, proposal_id) @@ -775,7 +847,7 @@ module supra_framework::multisig_voting { public fun create_test_proposal_generic( governance: &signer, use_generic_create_proposal_function: bool, - voters: vector
, + voters: vector
): u64 acquires VotingForum { // Register voting forum and create a proposal. register(governance); @@ -808,7 +880,7 @@ module supra_framework::multisig_voting { 2, voters, timestamp::now_seconds() + VOTING_DURATION_SECS, - metadata, + metadata ) } } @@ -823,10 +895,14 @@ module supra_framework::multisig_voting { if (is_multi_step) { let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); - resolve_proposal_v2(voting_forum_address, proposal_id, execution_hash); + resolve_proposal_v2( + voting_forum_address, proposal_id, execution_hash + ); if (finish_multi_step_execution) { - resolve_proposal_v2(voting_forum_address, proposal_id, vector::empty()); + resolve_proposal_v2( + voting_forum_address, proposal_id, vector::empty() + ); }; } else { let proposal = resolve(voting_forum_address, proposal_id); @@ -836,16 +912,14 @@ module supra_framework::multisig_voting { #[test_only] public fun create_test_proposal( - governance: &signer, - voters: vector
, + governance: &signer, voters: vector
): u64 acquires VotingForum { create_test_proposal_generic(governance, false, voters) } #[test_only] public fun create_proposal_with_empty_execution_hash_should_fail_generic( - governance: &signer, - is_multi_step: bool + governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); let governance_address = signer::address_of(governance); @@ -876,13 +950,15 @@ module supra_framework::multisig_voting { 2, voters, 100000, - simple_map::create>(), + simple_map::create>() ); }; } #[test(supra_framework = @supra_framework, governance = @0x123)] - public fun test_proposal_view_function(supra_framework: &signer, governance: &signer) acquires VotingForum { + public fun test_proposal_view_function( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -893,22 +969,51 @@ module supra_framework::multisig_voting { let proposal_id = create_test_proposal_generic(governance, true, voters); assert!(next_proposal_id(governance_address) == 1, 1); - assert!(get_proposer(governance_address, proposal_id) == governance_address, 2); + assert!( + get_proposer(governance_address, proposal_id) + == governance_address, + 2 + ); assert!(!is_voting_closed(governance_address, proposal_id), 3); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 4); - assert!(get_proposal_creation_secs(governance_address, proposal_id) == timestamp::now_seconds(), 5); - assert!(get_proposal_expiration_secs(governance_address, proposal_id) == timestamp::now_seconds() + VOTING_DURATION_SECS, 6); - assert!(get_execution_hash(governance_address, proposal_id) == vector[1], 7); - assert!(get_min_vote_threshold(governance_address, proposal_id) == 2, 8); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 4 + ); + assert!( + get_proposal_creation_secs(governance_address, proposal_id) + == timestamp::now_seconds(), + 5 + ); + assert!( + get_proposal_expiration_secs(governance_address, proposal_id) + == timestamp::now_seconds() + VOTING_DURATION_SECS, + 6 + ); + assert!( + get_execution_hash(governance_address, proposal_id) + == vector[1], + 7 + ); + assert!( + get_min_vote_threshold(governance_address, proposal_id) == 2, 8 + ); let (yes_vote, no_vote) = get_votes(governance_address, proposal_id); assert!(yes_vote == 0 && no_vote == 0, 9); assert!(!is_resolved(governance_address, proposal_id), 10); - assert!(!is_multi_step_proposal_in_execution(governance_address, proposal_id), 11); + assert!( + !is_multi_step_proposal_in_execution( + governance_address, proposal_id + ), + 11 + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x50010, location = Self)] - public fun test_vote_from_different_voter_fail(supra_framework: &signer, governance: &signer) acquires VotingForum { + public fun test_vote_from_different_voter_fail( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -920,13 +1025,21 @@ module supra_framework::multisig_voting { // Vote from differen account which is multisig owner list. let proof = TestProposal {}; - vote(&account::create_signer_for_test(@0xa11), &proof, governance_address, proposal_id, true); + vote( + &account::create_signer_for_test(@0xa11), + &proof, + governance_address, + proposal_id, + true + ); let TestProposal {} = proof; } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x8000D, location = Self)] - public fun test_vote_duplicate_fail(supra_framework: &signer, governance: &signer) acquires VotingForum { + public fun test_vote_duplicate_fail( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -938,14 +1051,28 @@ module supra_framework::multisig_voting { // Vote from differen account which is multisig owner list. let proof = TestProposal {}; - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); let TestProposal {} = proof; } #[test(governance = @0x123)] #[expected_failure(abort_code = 0x10004, location = Self)] - public fun create_proposal_with_empty_execution_hash_should_fail(governance: &signer) acquires VotingForum { + public fun create_proposal_with_empty_execution_hash_should_fail( + governance: &signer + ) acquires VotingForum { create_proposal_with_empty_execution_hash_should_fail_generic(governance, false); } @@ -971,63 +1098,88 @@ module supra_framework::multisig_voting { let governance_address = signer::address_of(governance); account::create_account_for_test(governance_address); let voters = vector[@0xa1, @0xa2, @0xa3]; - let proposal_id = create_test_proposal_generic(governance, use_create_multi_step, voters); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 0); + let proposal_id = + create_test_proposal_generic(governance, use_create_multi_step, voters); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 0 + ); // Vote. let proof = TestProposal {}; - vote( &account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); - vote(&account::create_signer_for_test(@0xa2), &proof, governance_address, proposal_id, true); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); + vote( + &account::create_signer_for_test(@0xa2), + &proof, + governance_address, + proposal_id, + true + ); let TestProposal {} = proof; // Resolve. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_SUCCEEDED, 1); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_SUCCEEDED, + 1 + ); // This if statement is specifically for the test `test_voting_passed_single_step_can_use_generic_function()`. // It's testing when we have a single-step proposal that was created by the single-step `create_proposal()`, // we should be able to successfully resolve it using the generic `resolve_proposal_v2` function. if (!use_create_multi_step && use_resolve_multi_step) { - resolve_proposal_v2(governance_address, proposal_id, vector::empty()); + resolve_proposal_v2( + governance_address, proposal_id, vector::empty() + ); } else { - resolve_proposal_for_test(governance_address, proposal_id, use_resolve_multi_step, true); + resolve_proposal_for_test( + governance_address, proposal_id, use_resolve_multi_step, true + ); }; let voting_forum = borrow_global>(governance_address); assert!(table::borrow(&voting_forum.proposals, proposal_id).is_resolved, 2); } #[test(supra_framework = @supra_framework, governance = @0x123)] - public entry fun test_voting_passed(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_passed( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_passed_generic(supra_framework, governance, false, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] - public entry fun test_voting_passed_multi_step(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_passed_multi_step( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_passed_generic(supra_framework, governance, true, true); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x5000a, location = Self)] public entry fun test_voting_passed_multi_step_cannot_use_single_step_resolve_function( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { test_voting_passed_generic(supra_framework, governance, true, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] public entry fun test_voting_passed_single_step_can_use_generic_function( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { test_voting_passed_generic(supra_framework, governance, false, true); } #[test_only] public entry fun test_cannot_resolve_twice_generic( - supra_framework: &signer, - governance: &signer, - is_multi_step: bool + supra_framework: &signer, governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -1037,41 +1189,64 @@ module supra_framework::multisig_voting { account::create_account_for_test(governance_address); let voters = vector[@0xa1, @0xa2, @0xa3]; let proposal_id = create_test_proposal_generic(governance, is_multi_step, voters); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 0); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 0 + ); // Vote. let proof = TestProposal {}; - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); - vote(&account::create_signer_for_test(@0xa2), &proof, governance_address, proposal_id, true); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); + vote( + &account::create_signer_for_test(@0xa2), + &proof, + governance_address, + proposal_id, + true + ); let TestProposal {} = proof; // Resolve. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_SUCCEEDED, 1); - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_SUCCEEDED, + 1 + ); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30003, location = Self)] - public entry fun test_cannot_resolve_twice(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_cannot_resolve_twice( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_cannot_resolve_twice_generic(supra_framework, governance, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30003, location = Self)] public entry fun test_cannot_resolve_twice_multi_step( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { test_cannot_resolve_twice_generic(supra_framework, governance, true); } #[test_only] public entry fun test_voting_passed_early_generic( - supra_framework: &signer, - governance: &signer, - is_multi_step: bool + supra_framework: &signer, governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -1081,64 +1256,107 @@ module supra_framework::multisig_voting { account::create_account_for_test(governance_address); let voters = vector[@0xa1, @0xa2, @0xa3]; let proposal_id = create_test_proposal_generic(governance, is_multi_step, voters); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 0); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 0 + ); // Assert that IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY has value `false` in proposal.metadata. if (is_multi_step) { - assert!(!is_multi_step_proposal_in_execution(governance_address, 0), 1); + assert!( + !is_multi_step_proposal_in_execution(governance_address, 0), + 1 + ); }; // Vote. let proof = TestProposal {}; - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); - vote(&account::create_signer_for_test(@0xa2), &proof, governance_address, proposal_id, true); - vote(&account::create_signer_for_test(@0xa3), &proof, governance_address, proposal_id, false); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); + vote( + &account::create_signer_for_test(@0xa2), + &proof, + governance_address, + proposal_id, + true + ); + vote( + &account::create_signer_for_test(@0xa3), + &proof, + governance_address, + proposal_id, + false + ); let TestProposal {} = proof; // Resolve early. Need to increase timestamp as resolution cannot happen in the same tx. timestamp::fast_forward_seconds(1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_SUCCEEDED, 2); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_SUCCEEDED, + 2 + ); if (is_multi_step) { // Assert that IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY still has value `false` in proposal.metadata before execution. - assert!(!is_multi_step_proposal_in_execution(governance_address, 0), 3); - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, false); + assert!( + !is_multi_step_proposal_in_execution(governance_address, 0), + 3 + ); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, false + ); // Assert that the multi-step proposal is in execution but not resolved yet. - assert!(is_multi_step_proposal_in_execution(governance_address, 0), 4); - let voting_forum = borrow_global_mut>(governance_address); + assert!( + is_multi_step_proposal_in_execution(governance_address, 0), + 4 + ); + let voting_forum = + borrow_global_mut>(governance_address); let proposal = table::borrow_mut(&mut voting_forum.proposals, proposal_id); assert!(!proposal.is_resolved, 5); }; - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); - let voting_forum = borrow_global_mut>(governance_address); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); + let voting_forum = + borrow_global_mut>(governance_address); assert!(table::borrow(&voting_forum.proposals, proposal_id).is_resolved, 6); // Assert that the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY value is set back to `false` upon successful resolution of this multi-step proposal. if (is_multi_step) { - assert!(!is_multi_step_proposal_in_execution(governance_address, 0), 7); + assert!( + !is_multi_step_proposal_in_execution(governance_address, 0), + 7 + ); }; } #[test(supra_framework = @supra_framework, governance = @0x123)] - public entry fun test_voting_passed_early(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_passed_early( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_passed_early_generic(supra_framework, governance, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] public entry fun test_voting_passed_early_multi_step( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { test_voting_passed_early_generic(supra_framework, governance, true); } #[test_only] public entry fun test_voting_passed_early_in_same_tx_should_fail_generic( - supra_framework: &signer, - governance: &signer, - is_multi_step: bool + supra_framework: &signer, governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -1147,37 +1365,51 @@ module supra_framework::multisig_voting { let voters = vector[@0xa1, @0xa2, @0xa3]; let proposal_id = create_test_proposal_generic(governance, is_multi_step, voters); let proof = TestProposal {}; - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); - vote(&account::create_signer_for_test(@0xa2), &proof, governance_address, proposal_id, true); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); + vote( + &account::create_signer_for_test(@0xa2), + &proof, + governance_address, + proposal_id, + true + ); let TestProposal {} = proof; // Resolving early should fail since timestamp hasn't changed since the last vote. - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30008, location = Self)] public entry fun test_voting_passed_early_in_same_tx_should_fail( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { - test_voting_passed_early_in_same_tx_should_fail_generic(supra_framework, governance, false); + test_voting_passed_early_in_same_tx_should_fail_generic( + supra_framework, governance, false + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30008, location = Self)] public entry fun test_voting_passed_early_in_same_tx_should_fail_multi_step( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { - test_voting_passed_early_in_same_tx_should_fail_generic(supra_framework, governance, true); + test_voting_passed_early_in_same_tx_should_fail_generic( + supra_framework, governance, true + ); } // Sure, #[test_only] public entry fun test_voting_failed_generic( - supra_framework: &signer, - governance: &signer, - is_multi_step: bool + supra_framework: &signer, governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -1190,33 +1422,54 @@ module supra_framework::multisig_voting { // Vote. let proof = TestProposal {}; - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, false); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + false + ); let TestProposal {} = proof; // Resolve. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_FAILED, 1); - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_FAILED, + 1 + ); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30002, location = Self)] - public entry fun test_voting_failed(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_failed( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_failed_generic(supra_framework, governance, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30002, location = Self)] - public entry fun test_voting_failed_multi_step(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_failed_multi_step( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_failed_generic(supra_framework, governance, true); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30005, location = Self)] public entry fun test_cannot_vote_after_voting_period_is_over( - supra_framework: signer, - governance: signer + supra_framework: signer, governance: signer ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(&supra_framework); @@ -1227,15 +1480,20 @@ module supra_framework::multisig_voting { // Voting period is over. Voting should now fail. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); let proof = TestProposal {}; - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); let TestProposal {} = proof; } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30009, location = Self)] public entry fun test_cannot_vote_after_multi_step_proposal_starts_executing( - supra_framework: signer, - governance: signer + supra_framework: signer, governance: signer ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(&supra_framework); @@ -1245,26 +1503,52 @@ module supra_framework::multisig_voting { account::create_account_for_test(governance_address); let voters = vector[@0xa1, @0xa2, @0xa3]; let proposal_id = create_test_proposal_generic(&governance, true, voters); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 0); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 0 + ); // Vote. let proof = TestProposal {}; - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); - vote(&account::create_signer_for_test(@0xa2), &proof, governance_address, proposal_id, true); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); + vote( + &account::create_signer_for_test(@0xa2), + &proof, + governance_address, + proposal_id, + true + ); // Resolve early. timestamp::fast_forward_seconds(1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_SUCCEEDED, 1); - resolve_proposal_for_test(governance_address, proposal_id, true, false); - vote(&account::create_signer_for_test(@0xa3), &proof, governance_address, proposal_id, false); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_SUCCEEDED, + 1 + ); + resolve_proposal_for_test( + governance_address, proposal_id, true, false + ); + vote( + &account::create_signer_for_test(@0xa3), + &proof, + governance_address, + proposal_id, + false + ); let TestProposal {} = proof; } #[test_only] public entry fun test_voting_failed_early_generic( - supra_framework: &signer, - governance: &signer, - is_multi_step: bool + supra_framework: &signer, governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -1277,33 +1561,54 @@ module supra_framework::multisig_voting { // Vote. let proof = TestProposal {}; - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, false); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + false + ); let TestProposal {} = proof; // Resolve. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_FAILED, 1); - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_FAILED, + 1 + ); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30002, location = Self)] - public entry fun test_voting_failed_early(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_failed_early( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_failed_early_generic(supra_framework, governance, true); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30002, location = Self)] public entry fun test_voting_failed_early_multi_step( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { test_voting_failed_early_generic(supra_framework, governance, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] - public entry fun test_replace_execution_hash(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_replace_execution_hash( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -1312,17 +1617,37 @@ module supra_framework::multisig_voting { account::create_account_for_test(governance_address); let voters = vector[@0xa1, @0xa2, @0xa3]; let proposal_id = create_test_proposal_generic(governance, true, voters); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 0); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 0 + ); // Vote. let proof = TestProposal {}; - vote(&account::create_signer_for_test(@0xa1), &proof, governance_address, proposal_id, true); - vote(&account::create_signer_for_test(@0xa2), &proof, governance_address, proposal_id, true); + vote( + &account::create_signer_for_test(@0xa1), + &proof, + governance_address, + proposal_id, + true + ); + vote( + &account::create_signer_for_test(@0xa2), + &proof, + governance_address, + proposal_id, + true + ); let TestProposal {} = proof; // Resolve. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_SUCCEEDED, 1); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_SUCCEEDED, + 1 + ); resolve_proposal_v2(governance_address, proposal_id, vector[10u8]); let voting_forum = borrow_global>(governance_address); diff --git a/aptos-move/framework/supra-framework/sources/object.move b/aptos-move/framework/supra-framework/sources/object.move index b71a844345af8..9b0c9cd0d962b 100644 --- a/aptos-move/framework/supra-framework/sources/object.move +++ b/aptos-move/framework/supra-framework/sources/object.move @@ -90,7 +90,8 @@ module supra_framework::object { const OBJECT_FROM_SEED_ADDRESS_SCHEME: u8 = 0xFE; /// Address where unwanted objects can be forcefully transferred to. - const BURN_ADDRESS: address = @0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + const BURN_ADDRESS: address = + @0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; #[resource_group_member(group = supra_framework::object::ObjectGroup)] /// The core of the object model that defines ownership, transferability, and events. @@ -103,14 +104,14 @@ module supra_framework::object { /// transfers bypassing the use of a TransferRef. allow_ungated_transfer: bool, /// Emitted events upon transferring of ownership. - transfer_events: event::EventHandle, + transfer_events: event::EventHandle } #[resource_group_member(group = supra_framework::object::ObjectGroup)] /// This is added to objects that are burnt (ownership transferred to BURN_ADDRESS). struct TombStone has key { /// Track the previous owner before the object is burnt so they can reclaim later if so desired. - original_owner: address, + original_owner: address } #[resource_group_member(group = supra_framework::object::ObjectGroup)] @@ -126,48 +127,48 @@ module supra_framework::object { /// by any other module than the module that defined T. Similarly, the module that defines T /// can remove it from storage at any point in time. struct Object has copy, drop, store { - inner: address, + inner: address } /// This is a one time ability given to the creator to configure the object as necessary struct ConstructorRef has drop { self: address, /// True if the object can be deleted. Named objects are not deletable. - can_delete: bool, + can_delete: bool } /// Used to remove an object from storage. struct DeleteRef has drop, store { - self: address, + self: address } /// Used to create events or move additional resources into object storage. struct ExtendRef has drop, store { - self: address, + self: address } /// Used to create LinearTransferRef, hence ownership transfer. struct TransferRef has drop, store { - self: address, + self: address } /// Used to perform transfers. This locks transferring ability to a single time use bound to /// the current owner. struct LinearTransferRef has drop { self: address, - owner: address, + owner: address } /// Used to create derived objects from a given objects. struct DeriveRef has drop, store { - self: address, + self: address } /// Emitted whenever the object's owner field is changed. struct TransferEvent has drop, store { object: address, from: address, - to: address, + to: address } #[event] @@ -175,7 +176,7 @@ module supra_framework::object { struct Transfer has drop, store { object: address, from: address, - to: address, + to: address } #[view] @@ -213,10 +214,14 @@ module supra_framework::object { from_bcs::to_address(hash::sha3_256(bytes)) } - native fun create_user_derived_object_address_impl(source: address, derive_from: address): address; + native fun create_user_derived_object_address_impl( + source: address, derive_from: address + ): address; /// Derives an object address from the source address and an object: sha3_256([source | object addr | 0xFC]). - public fun create_user_derived_object_address(source: address, derive_from: address): address { + public fun create_user_derived_object_address( + source: address, derive_from: address + ): address { if (std::features::object_native_derived_address_enabled()) { create_user_derived_object_address_impl(source, derive_from) } else { @@ -228,7 +233,9 @@ module supra_framework::object { } /// Derives an object from an Account GUID. - public fun create_guid_object_address(source: address, creation_num: u64): address { + public fun create_guid_object_address( + source: address, creation_num: u64 + ): address { let id = guid::create_id(source, creation_num); let bytes = bcs::to_bytes(&id); vector::push_back(&mut bytes, OBJECT_FROM_GUID_ADDRESS_SCHEME); @@ -257,8 +264,11 @@ module supra_framework::object { /// Create a new object whose address is derived based on the creator account address and another object. /// Derivde objects, similar to named objects, cannot be deleted. - public(friend) fun create_user_derived_object(creator_address: address, derive_ref: &DeriveRef): ConstructorRef { - let obj_addr = create_user_derived_object_address(creator_address, derive_ref.self); + public(friend) fun create_user_derived_object( + creator_address: address, derive_ref: &DeriveRef + ): ConstructorRef { + let obj_addr = + create_user_derived_object_address(creator_address, derive_ref.self); create_object_internal(creator_address, obj_addr, false) } @@ -279,8 +289,7 @@ module supra_framework::object { /// Create a sticky object at a specific address. Only used by supra_framework::coin. public(friend) fun create_sticky_object_at_address( - owner_address: address, - object_address: address, + owner_address: address, object_address: address ): ConstructorRef { create_object_internal(owner_address, object_address, false) } @@ -309,7 +318,9 @@ module supra_framework::object { create_object_from_guid(signer::address_of(creator), guid) } - fun create_object_from_guid(creator_address: address, guid: guid::GUID): ConstructorRef { + fun create_object_from_guid( + creator_address: address, guid: guid::GUID + ): ConstructorRef { let bytes = bcs::to_bytes(&guid); vector::push_back(&mut bytes, OBJECT_FROM_GUID_ADDRESS_SCHEME); let obj_addr = from_bcs::to_address(hash::sha3_256(bytes)); @@ -319,7 +330,7 @@ module supra_framework::object { fun create_object_internal( creator_address: address, object: address, - can_delete: bool, + can_delete: bool ): ConstructorRef { assert!(!exists(object), error::already_exists(EOBJECT_EXISTS)); @@ -333,8 +344,8 @@ module supra_framework::object { guid_creation_num, owner: creator_address, allow_ungated_transfer: true, - transfer_events: event::new_event_handle(transfer_events_guid), - }, + transfer_events: event::new_event_handle(transfer_events_guid) + } ); ConstructorRef { self: object, can_delete } } @@ -354,7 +365,10 @@ module supra_framework::object { /// Generates the TransferRef, which can be used to manage object transfers. public fun generate_transfer_ref(ref: &ConstructorRef): TransferRef { - assert!(!exists(ref.self), error::permission_denied(EOBJECT_NOT_TRANSFERRABLE)); + assert!( + !exists(ref.self), + error::permission_denied(EOBJECT_NOT_TRANSFERRABLE) + ); TransferRef { self: ref.self } } @@ -394,7 +408,7 @@ module supra_framework::object { /// Generate a new event handle. public fun new_event_handle( - object: &signer, + object: &signer ): event::EventHandle acquires ObjectCore { event::new_event_handle(create_guid(object)) } @@ -418,11 +432,11 @@ module supra_framework::object { guid_creation_num: _, owner: _, allow_ungated_transfer: _, - transfer_events, + transfer_events } = object_core; if (exists(ref.self)) { - let Untransferable {} = move_from(ref.self); + let Untransferable {} = move_from(ref.self); }; event::destroy_handle(transfer_events); @@ -458,25 +472,33 @@ module supra_framework::object { /// Enable direct transfer. public fun enable_ungated_transfer(ref: &TransferRef) acquires ObjectCore { - assert!(!exists(ref.self), error::permission_denied(EOBJECT_NOT_TRANSFERRABLE)); + assert!( + !exists(ref.self), + error::permission_denied(EOBJECT_NOT_TRANSFERRABLE) + ); let object = borrow_global_mut(ref.self); object.allow_ungated_transfer = true; } /// Create a LinearTransferRef for a one-time transfer. This requires that the owner at the /// time of generation is the owner at the time of transferring. - public fun generate_linear_transfer_ref(ref: &TransferRef): LinearTransferRef acquires ObjectCore { - assert!(!exists(ref.self), error::permission_denied(EOBJECT_NOT_TRANSFERRABLE)); + public fun generate_linear_transfer_ref( + ref: &TransferRef + ): LinearTransferRef acquires ObjectCore { + assert!( + !exists(ref.self), + error::permission_denied(EOBJECT_NOT_TRANSFERRABLE) + ); let owner = owner(Object { inner: ref.self }); - LinearTransferRef { - self: ref.self, - owner, - } + LinearTransferRef { self: ref.self, owner } } /// Transfer to the destination address using a LinearTransferRef. public fun transfer_with_ref(ref: LinearTransferRef, to: address) acquires ObjectCore, TombStone { - assert!(!exists(ref.self), error::permission_denied(EOBJECT_NOT_TRANSFERRABLE)); + assert!( + !exists(ref.self), + error::permission_denied(EOBJECT_NOT_TRANSFERRABLE) + ); // Undo soft burn if present as we don't want the original owner to be able to reclaim by calling unburn later. if (exists(ref.self)) { @@ -486,24 +508,16 @@ module supra_framework::object { let object = borrow_global_mut(ref.self); assert!( object.owner == ref.owner, - error::permission_denied(ENOT_OBJECT_OWNER), + error::permission_denied(ENOT_OBJECT_OWNER) ); if (std::features::module_event_migration_enabled()) { event::emit( - Transfer { - object: ref.self, - from: object.owner, - to, - }, + Transfer { object: ref.self, from: object.owner, to } ); }; event::emit_event( &mut object.transfer_events, - TransferEvent { - object: ref.self, - from: object.owner, - to, - }, + TransferEvent { object: ref.self, from: object.owner, to } ); object.owner = to; } @@ -512,7 +526,7 @@ module supra_framework::object { public entry fun transfer_call( owner: &signer, object: address, - to: address, + to: address ) acquires ObjectCore { transfer_raw(owner, object, to) } @@ -522,7 +536,7 @@ module supra_framework::object { public entry fun transfer( owner: &signer, object: Object, - to: address, + to: address ) acquires ObjectCore { transfer_raw(owner, object.inner, to) } @@ -534,7 +548,7 @@ module supra_framework::object { public fun transfer_raw( owner: &signer, object: address, - to: address, + to: address ) acquires ObjectCore { let owner_address = signer::address_of(owner); verify_ungated_and_descendant(owner_address, object); @@ -546,20 +560,12 @@ module supra_framework::object { if (object_core.owner != to) { if (std::features::module_event_migration_enabled()) { event::emit( - Transfer { - object, - from: object_core.owner, - to, - }, + Transfer { object, from: object_core.owner, to } ); }; event::emit_event( &mut object_core.transfer_events, - TransferEvent { - object, - from: object_core.owner, - to, - }, + TransferEvent { object, from: object_core.owner, to } ); object_core.owner = to; }; @@ -569,7 +575,7 @@ module supra_framework::object { public entry fun transfer_to_object( owner: &signer, object: Object, - to: Object, + to: Object ) acquires ObjectCore { transfer(owner, object, to.inner) } @@ -577,17 +583,19 @@ module supra_framework::object { /// This checks that the destination address is eventually owned by the owner and that each /// object between the two allows for ungated transfers. Note, this is limited to a depth of 8 /// objects may have cyclic dependencies. - fun verify_ungated_and_descendant(owner: address, destination: address) acquires ObjectCore { + fun verify_ungated_and_descendant( + owner: address, destination: address + ) acquires ObjectCore { let current_address = destination; assert!( exists(current_address), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); let object = borrow_global(current_address); assert!( object.allow_ungated_transfer, - error::permission_denied(ENO_UNGATED_TRANSFERS), + error::permission_denied(ENO_UNGATED_TRANSFERS) ); let current_address = object.owner; @@ -599,12 +607,12 @@ module supra_framework::object { // object's owner is not an object. So we return a more sensible error. assert!( exists(current_address), - error::permission_denied(ENOT_OBJECT_OWNER), + error::permission_denied(ENOT_OBJECT_OWNER) ); let object = borrow_global(current_address); assert!( object.allow_ungated_transfer, - error::permission_denied(ENO_UNGATED_TRANSFERS), + error::permission_denied(ENO_UNGATED_TRANSFERS) ); current_address = object.owner; }; @@ -615,7 +623,9 @@ module supra_framework::object { /// Original owners can reclaim burnt objects any time in the future by calling unburn. public entry fun burn(owner: &signer, object: Object) acquires ObjectCore { let original_owner = signer::address_of(owner); - assert!(is_owner(object, original_owner), error::permission_denied(ENOT_OBJECT_OWNER)); + assert!( + is_owner(object, original_owner), error::permission_denied(ENOT_OBJECT_OWNER) + ); let object_addr = object.inner; move_to(&create_signer(object_addr), TombStone { original_owner }); transfer_raw_inner(object_addr, BURN_ADDRESS); @@ -623,14 +633,19 @@ module supra_framework::object { /// Allow origin owners to reclaim any objects they previous burnt. public entry fun unburn( - original_owner: &signer, - object: Object, + original_owner: &signer, object: Object ) acquires TombStone, ObjectCore { let object_addr = object.inner; - assert!(exists(object_addr), error::invalid_argument(EOBJECT_NOT_BURNT)); + assert!( + exists(object_addr), error::invalid_argument(EOBJECT_NOT_BURNT) + ); - let TombStone { original_owner: original_owner_addr } = move_from(object_addr); - assert!(original_owner_addr == signer::address_of(original_owner), error::permission_denied(ENOT_OBJECT_OWNER)); + let TombStone { original_owner: original_owner_addr } = + move_from(object_addr); + assert!( + original_owner_addr == signer::address_of(original_owner), + error::permission_denied(ENOT_OBJECT_OWNER) + ); transfer_raw_inner(object_addr, original_owner_addr); } @@ -639,7 +654,7 @@ module supra_framework::object { public fun ungated_transfer_allowed(object: Object): bool acquires ObjectCore { assert!( exists(object.inner), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); borrow_global(object.inner).allow_ungated_transfer } @@ -648,7 +663,7 @@ module supra_framework::object { public fun owner(object: Object): address acquires ObjectCore { assert!( exists(object.inner), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); borrow_global(object.inner).owner } @@ -667,7 +682,7 @@ module supra_framework::object { assert!( exists(current_address), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); let object = borrow_global(current_address); @@ -707,14 +722,14 @@ module supra_framework::object { #[test_only] struct HeroEquipEvent has drop, store { - weapon_id: Option>, + weapon_id: Option> } #[test_only] #[resource_group_member(group = supra_framework::object::ObjectGroup)] struct Hero has key { equip_events: event::EventHandle, - weapon: Option>, + weapon: Option> } #[test_only] @@ -730,8 +745,8 @@ module supra_framework::object { &hero_signer, Hero { weapon: option::none(), - equip_events: event::new_event_handle(guid_for_equip_events), - }, + equip_events: event::new_event_handle(guid_for_equip_events) + } ); let hero = object_from_constructor_ref(&hero_constructor_ref); @@ -751,14 +766,14 @@ module supra_framework::object { public fun hero_equip( owner: &signer, hero: Object, - weapon: Object, + weapon: Object ) acquires Hero, ObjectCore { transfer_to_object(owner, weapon, hero); let hero_obj = borrow_global_mut(object_address(&hero)); option::fill(&mut hero_obj.weapon, weapon); event::emit_event( &mut hero_obj.equip_events, - HeroEquipEvent { weapon_id: option::some(weapon) }, + HeroEquipEvent { weapon_id: option::some(weapon) } ); } @@ -766,14 +781,14 @@ module supra_framework::object { public fun hero_unequip( owner: &signer, hero: Object, - weapon: Object, + weapon: Object ) acquires Hero, ObjectCore { transfer(owner, weapon, signer::address_of(owner)); let hero = borrow_global_mut(object_address(&hero)); option::extract(&mut hero.weapon); event::emit_event( &mut hero.equip_events, - HeroEquipEvent { weapon_id: option::none() }, + HeroEquipEvent { weapon_id: option::none() } ); } @@ -914,7 +929,9 @@ module supra_framework::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 131078, location = Self)] - fun test_exceeding_maximum_object_nesting_owns_should_fail(creator: &signer) acquires ObjectCore { + fun test_exceeding_maximum_object_nesting_owns_should_fail( + creator: &signer + ) acquires ObjectCore { let obj1 = create_simple_object(creator, b"1"); let obj2 = create_simple_object(creator, b"2"); let obj3 = create_simple_object(creator, b"3"); @@ -949,7 +966,9 @@ module supra_framework::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 131078, location = Self)] - fun test_exceeding_maximum_object_nesting_transfer_should_fail(creator: &signer) acquires ObjectCore { + fun test_exceeding_maximum_object_nesting_transfer_should_fail( + creator: &signer + ) acquires ObjectCore { let obj1 = create_simple_object(creator, b"1"); let obj2 = create_simple_object(creator, b"2"); let obj3 = create_simple_object(creator, b"3"); @@ -1003,7 +1022,9 @@ module supra_framework::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 327689, location = Self)] - fun test_untransferable_direct_ownership_gen_transfer_ref(creator: &signer) acquires ObjectCore { + fun test_untransferable_direct_ownership_gen_transfer_ref( + creator: &signer + ) acquires ObjectCore { let (hero_constructor_ref, _) = create_hero(creator); set_untransferable(&hero_constructor_ref); generate_transfer_ref(&hero_constructor_ref); @@ -1011,7 +1032,9 @@ module supra_framework::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 327689, location = Self)] - fun test_untransferable_direct_ownership_gen_linear_transfer_ref(creator: &signer) acquires ObjectCore { + fun test_untransferable_direct_ownership_gen_linear_transfer_ref( + creator: &signer + ) acquires ObjectCore { let (hero_constructor_ref, _) = create_hero(creator); let transfer_ref = generate_transfer_ref(&hero_constructor_ref); set_untransferable(&hero_constructor_ref); @@ -1020,7 +1043,9 @@ module supra_framework::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 327689, location = Self)] - fun test_untransferable_direct_ownership_with_linear_transfer_ref(creator: &signer) acquires ObjectCore, TombStone { + fun test_untransferable_direct_ownership_with_linear_transfer_ref( + creator: &signer + ) acquires ObjectCore, TombStone { let (hero_constructor_ref, _) = create_hero(creator); let transfer_ref = generate_transfer_ref(&hero_constructor_ref); let linear_transfer_ref = generate_linear_transfer_ref(&transfer_ref); @@ -1040,7 +1065,9 @@ module supra_framework::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 327689, location = Self)] - fun test_untransferable_indirect_ownership_gen_transfer_ref(creator: &signer) acquires ObjectCore { + fun test_untransferable_indirect_ownership_gen_transfer_ref( + creator: &signer + ) acquires ObjectCore { let (_, hero) = create_hero(creator); let (weapon_constructor_ref, weapon) = create_weapon(creator); transfer_to_object(creator, weapon, hero); @@ -1050,7 +1077,9 @@ module supra_framework::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 327689, location = Self)] - fun test_untransferable_indirect_ownership_gen_linear_transfer_ref(creator: &signer) acquires ObjectCore { + fun test_untransferable_indirect_ownership_gen_linear_transfer_ref( + creator: &signer + ) acquires ObjectCore { let (_, hero) = create_hero(creator); let (weapon_constructor_ref, weapon) = create_weapon(creator); transfer_to_object(creator, weapon, hero); @@ -1061,7 +1090,9 @@ module supra_framework::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 327689, location = Self)] - fun test_untransferable_indirect_ownership_with_linear_transfer_ref(creator: &signer) acquires ObjectCore, TombStone { + fun test_untransferable_indirect_ownership_with_linear_transfer_ref( + creator: &signer + ) acquires ObjectCore, TombStone { let (_, hero) = create_hero(creator); let (weapon_constructor_ref, weapon) = create_weapon(creator); transfer_to_object(creator, weapon, hero); diff --git a/aptos-move/framework/supra-framework/sources/object.spec.move b/aptos-move/framework/supra-framework/sources/object.spec.move index 12cad2fec0936..d648c976f4b9f 100644 --- a/aptos-move/framework/supra-framework/sources/object.spec.move +++ b/aptos-move/framework/supra-framework/sources/object.spec.move @@ -56,7 +56,6 @@ spec supra_framework::object { ensures [abstract] result == spec_exists_at(object); } - spec address_to_object(object: address): Object { aborts_if !exists(object); aborts_if !spec_exists_at(object); @@ -70,20 +69,21 @@ spec supra_framework::object { aborts_if exists(unique_address); ensures exists(unique_address); - ensures global(unique_address) == ObjectCore { - guid_creation_num: INIT_GUID_CREATION_NUM + 1, - owner: owner_address, - allow_ungated_transfer: true, - transfer_events: event::EventHandle { - counter: 0, - guid: guid::GUID { - id: guid::ID { - creation_num: INIT_GUID_CREATION_NUM, - addr: unique_address, + ensures global(unique_address) + == ObjectCore { + guid_creation_num: INIT_GUID_CREATION_NUM + 1, + owner: owner_address, + allow_ungated_transfer: true, + transfer_events: event::EventHandle { + counter: 0, + guid: guid::GUID { + id: guid::ID { + creation_num: INIT_GUID_CREATION_NUM, + addr: unique_address + } } } - } - }; + }; ensures result == ConstructorRef { self: unique_address, can_delete: true }; } @@ -94,20 +94,21 @@ spec supra_framework::object { aborts_if exists(unique_address); ensures exists(unique_address); - ensures global(unique_address) == ObjectCore { - guid_creation_num: INIT_GUID_CREATION_NUM + 1, - owner: owner_address, - allow_ungated_transfer: true, - transfer_events: event::EventHandle { - counter: 0, - guid: guid::GUID { - id: guid::ID { - creation_num: INIT_GUID_CREATION_NUM, - addr: unique_address, + ensures global(unique_address) + == ObjectCore { + guid_creation_num: INIT_GUID_CREATION_NUM + 1, + owner: owner_address, + allow_ungated_transfer: true, + transfer_events: event::EventHandle { + counter: 0, + guid: guid::GUID { + id: guid::ID { + creation_num: INIT_GUID_CREATION_NUM, + addr: unique_address + } } } - } - }; + }; ensures result == ConstructorRef { self: unique_address, can_delete: false }; } @@ -122,21 +123,24 @@ spec supra_framework::object { spec create_user_derived_object_address_impl(source: address, derive_from: address): address { pragma opaque; - ensures [abstract] result == spec_create_user_derived_object_address_impl(source, derive_from); + ensures [abstract] result + == spec_create_user_derived_object_address_impl(source, derive_from); } spec create_user_derived_object_address(source: address, derive_from: address): address { pragma opaque; pragma aborts_if_is_strict = false; aborts_if [abstract] false; - ensures [abstract] result == spec_create_user_derived_object_address(source, derive_from); + ensures [abstract] result + == spec_create_user_derived_object_address(source, derive_from); } spec create_guid_object_address(source: address, creation_num: u64): address { pragma opaque; pragma aborts_if_is_strict = false; aborts_if [abstract] false; - ensures [abstract] result == spec_create_guid_object_address(source, creation_num); + ensures [abstract] result + == spec_create_guid_object_address(source, creation_num); } spec object_address(object: &Object): address { @@ -156,42 +160,46 @@ spec supra_framework::object { aborts_if exists(obj_addr); ensures exists(obj_addr); - ensures global(obj_addr) == ObjectCore { - guid_creation_num: INIT_GUID_CREATION_NUM + 1, - owner: creator_address, - allow_ungated_transfer: true, - transfer_events: event::EventHandle { - counter: 0, - guid: guid::GUID { - id: guid::ID { - creation_num: INIT_GUID_CREATION_NUM, - addr: obj_addr, + ensures global(obj_addr) + == ObjectCore { + guid_creation_num: INIT_GUID_CREATION_NUM + 1, + owner: creator_address, + allow_ungated_transfer: true, + transfer_events: event::EventHandle { + counter: 0, + guid: guid::GUID { + id: guid::ID { + creation_num: INIT_GUID_CREATION_NUM, + addr: obj_addr + } } } - } - }; + }; ensures result == ConstructorRef { self: obj_addr, can_delete: false }; } spec create_user_derived_object(creator_address: address, derive_ref: &DeriveRef): ConstructorRef { - let obj_addr = spec_create_user_derived_object_address(creator_address, derive_ref.self); + let obj_addr = spec_create_user_derived_object_address( + creator_address, derive_ref.self + ); aborts_if exists(obj_addr); ensures exists(obj_addr); - ensures global(obj_addr) == ObjectCore { - guid_creation_num: INIT_GUID_CREATION_NUM + 1, - owner: creator_address, - allow_ungated_transfer: true, - transfer_events: event::EventHandle { - counter: 0, - guid: guid::GUID { - id: guid::ID { - creation_num: INIT_GUID_CREATION_NUM, - addr: obj_addr, + ensures global(obj_addr) + == ObjectCore { + guid_creation_num: INIT_GUID_CREATION_NUM + 1, + owner: creator_address, + allow_ungated_transfer: true, + transfer_events: event::EventHandle { + counter: 0, + guid: guid::GUID { + id: guid::ID { + creation_num: INIT_GUID_CREATION_NUM, + addr: obj_addr + } } } - } - }; + }; ensures result == ConstructorRef { self: obj_addr, can_delete: false }; } @@ -204,12 +212,7 @@ spec supra_framework::object { let creation_num = object_data.guid_creation_num; let addr = signer::address_of(creator); - let guid = guid::GUID { - id: guid::ID { - creation_num, - addr, - } - }; + let guid = guid::GUID { id: guid::ID { creation_num, addr } }; let bytes_spec = bcs::to_bytes(guid); let bytes = concat(bytes_spec, vec(OBJECT_FROM_GUID_ADDRESS_SCHEME)); @@ -218,24 +221,24 @@ spec supra_framework::object { aborts_if exists(obj_addr); aborts_if !from_bcs::deserializable
(hash_bytes); - ensures global(addr).guid_creation_num == old( - global(addr) - ).guid_creation_num + 1; + ensures global(addr).guid_creation_num + == old(global(addr)).guid_creation_num + 1; ensures exists(obj_addr); - ensures global(obj_addr) == ObjectCore { - guid_creation_num: INIT_GUID_CREATION_NUM + 1, - owner: addr, - allow_ungated_transfer: true, - transfer_events: event::EventHandle { - counter: 0, - guid: guid::GUID { - id: guid::ID { - creation_num: INIT_GUID_CREATION_NUM, - addr: obj_addr, + ensures global(obj_addr) + == ObjectCore { + guid_creation_num: INIT_GUID_CREATION_NUM + 1, + owner: addr, + allow_ungated_transfer: true, + transfer_events: event::EventHandle { + counter: 0, + guid: guid::GUID { + id: guid::ID { + creation_num: INIT_GUID_CREATION_NUM, + addr: obj_addr + } } } - } - }; + }; ensures result == ConstructorRef { self: obj_addr, can_delete: true }; } @@ -247,12 +250,7 @@ spec supra_framework::object { let creation_num = object_data.guid_creation_num; let addr = signer::address_of(creator); - let guid = guid::GUID { - id: guid::ID { - creation_num, - addr, - } - }; + let guid = guid::GUID { id: guid::ID { creation_num, addr } }; let bytes_spec = bcs::to_bytes(guid); let bytes = concat(bytes_spec, vec(OBJECT_FROM_GUID_ADDRESS_SCHEME)); @@ -261,22 +259,24 @@ spec supra_framework::object { aborts_if exists(obj_addr); aborts_if !from_bcs::deserializable
(hash_bytes); - ensures global(addr).guid_creation_num == old(global(addr)).guid_creation_num + 1; + ensures global(addr).guid_creation_num + == old(global(addr)).guid_creation_num + 1; ensures exists(obj_addr); - ensures global(obj_addr) == ObjectCore { - guid_creation_num: INIT_GUID_CREATION_NUM + 1, - owner: addr, - allow_ungated_transfer: true, - transfer_events: event::EventHandle { - counter: 0, - guid: guid::GUID { - id: guid::ID { - creation_num: INIT_GUID_CREATION_NUM, - addr: obj_addr, + ensures global(obj_addr) + == ObjectCore { + guid_creation_num: INIT_GUID_CREATION_NUM + 1, + owner: addr, + allow_ungated_transfer: true, + transfer_events: event::EventHandle { + counter: 0, + guid: guid::GUID { + id: guid::ID { + creation_num: INIT_GUID_CREATION_NUM, + addr: obj_addr + } } } - } - }; + }; ensures result == ConstructorRef { self: obj_addr, can_delete: true }; } @@ -289,20 +289,21 @@ spec supra_framework::object { aborts_if !from_bcs::deserializable
(hash_bytes); ensures exists(obj_addr); - ensures global(obj_addr) == ObjectCore { - guid_creation_num: INIT_GUID_CREATION_NUM + 1, - owner: creator_address, - allow_ungated_transfer: true, - transfer_events: event::EventHandle { - counter: 0, - guid: guid::GUID { - id: guid::ID { - creation_num: INIT_GUID_CREATION_NUM, - addr: obj_addr, + ensures global(obj_addr) + == ObjectCore { + guid_creation_num: INIT_GUID_CREATION_NUM + 1, + owner: creator_address, + allow_ungated_transfer: true, + transfer_events: event::EventHandle { + counter: 0, + guid: guid::GUID { + id: guid::ID { + creation_num: INIT_GUID_CREATION_NUM, + addr: obj_addr + } } } - } - }; + }; ensures result == ConstructorRef { self: obj_addr, can_delete: true }; } @@ -312,16 +313,15 @@ spec supra_framework::object { } spec create_object_internal( - creator_address: address, - object: address, - can_delete: bool, + creator_address: address, object: address, can_delete: bool ): ConstructorRef { // property 1: Creating an object twice on the same address must never occur. /// [high-level-req-1] aborts_if exists(object); ensures exists(object); // property 6: Object addresses must not overlap with other addresses in different domains. - ensures global(object).guid_creation_num == INIT_GUID_CREATION_NUM + 1; + ensures global(object).guid_creation_num + == INIT_GUID_CREATION_NUM + 1; ensures result == ConstructorRef { self: object, can_delete }; } @@ -347,17 +347,16 @@ spec supra_framework::object { let object_data = global(signer::address_of(object)); aborts_if object_data.guid_creation_num + 1 > MAX_U64; - ensures result == guid::GUID { - id: guid::ID { - creation_num: object_data.guid_creation_num, - addr: signer::address_of(object) - } - }; + ensures result + == guid::GUID { + id: guid::ID { + creation_num: object_data.guid_creation_num, + addr: signer::address_of(object) + } + }; } - spec new_event_handle( - object: &signer, - ): event::EventHandle { + spec new_event_handle(object: &signer): event::EventHandle { aborts_if !exists(signer::address_of(object)); //Guid properties let object_data = global(signer::address_of(object)); @@ -369,10 +368,7 @@ spec supra_framework::object { addr: signer::address_of(object) } }; - ensures result == event::EventHandle { - counter: 0, - guid, - }; + ensures result == event::EventHandle { counter: 0, guid }; } spec object_from_delete_ref(ref: &DeleteRef): Object { @@ -401,19 +397,14 @@ spec supra_framework::object { spec generate_transfer_ref(ref: &ConstructorRef): TransferRef { aborts_if exists(ref.self); - ensures result == TransferRef { - self: ref.self, - }; + ensures result == TransferRef { self: ref.self }; } spec generate_linear_transfer_ref(ref: &TransferRef): LinearTransferRef { aborts_if exists(ref.self); aborts_if !exists(ref.self); let owner = global(ref.self).owner; - ensures result == LinearTransferRef { - self: ref.self, - owner, - }; + ensures result == LinearTransferRef { self: ref.self, owner }; } spec transfer_with_ref(ref: LinearTransferRef, to: address) { @@ -426,9 +417,7 @@ spec supra_framework::object { } spec transfer_call( - owner: &signer, - object: address, - to: address, + owner: &signer, object: address, to: address ) { pragma aborts_if_is_partial; // TODO: Verify the link list loop in verify_ungated_and_descendant @@ -437,11 +426,7 @@ spec supra_framework::object { aborts_if !global(object).allow_ungated_transfer; } - spec transfer( - owner: &signer, - object: Object, - to: address, - ) { + spec transfer(owner: &signer, object: Object, to: address) { pragma aborts_if_is_partial; // TODO: Verify the link list loop in verify_ungated_and_descendant let owner_address = signer::address_of(owner); @@ -451,9 +436,7 @@ spec supra_framework::object { } spec transfer_raw( - owner: &signer, - object: address, - to: address, + owner: &signer, object: address, to: address ) { pragma aborts_if_is_partial; // TODO: Verify the link list loop in verify_ungated_and_descendant @@ -462,11 +445,7 @@ spec supra_framework::object { aborts_if !global(object).allow_ungated_transfer; } - spec transfer_to_object ( - owner: &signer, - object: Object, - to: Object, - ) { + spec transfer_to_object(owner: &signer, object: Object, to: Object) { pragma aborts_if_is_partial; // TODO: Verify the link list loop in verify_ungated_and_descendant let owner_address = signer::address_of(owner); diff --git a/aptos-move/framework/supra-framework/sources/object_code_deployment.move b/aptos-move/framework/supra-framework/sources/object_code_deployment.move index 3a3825ebc7cd7..e57355bb5a738 100644 --- a/aptos-move/framework/supra-framework/sources/object_code_deployment.move +++ b/aptos-move/framework/supra-framework/sources/object_code_deployment.move @@ -54,25 +54,25 @@ module supra_framework::object_code_deployment { /// Internal struct, attached to the object, that holds Refs we need to manage the code deployment (i.e. upgrades). struct ManagingRefs has key { /// We need to keep the extend ref to be able to generate the signer to upgrade existing code. - extend_ref: ExtendRef, + extend_ref: ExtendRef } #[event] /// Event emitted when code is published to an object. struct Publish has drop, store { - object_address: address, + object_address: address } #[event] /// Event emitted when code in an existing object is upgraded. struct Upgrade has drop, store { - object_address: address, + object_address: address } #[event] /// Event emitted when code in an existing object is made immutable. struct Freeze has drop, store { - object_address: address, + object_address: address } /// Creates a new object with a unique address derived from the publisher address and the object seed. @@ -82,11 +82,11 @@ module supra_framework::object_code_deployment { public entry fun publish( publisher: &signer, metadata_serialized: vector, - code: vector>, + code: vector> ) { assert!( features::is_object_code_deployment_enabled(), - error::unavailable(EOBJECT_CODE_DEPLOYMENT_NOT_SUPPORTED), + error::unavailable(EOBJECT_CODE_DEPLOYMENT_NOT_SUPPORTED) ); let publisher_address = signer::address_of(publisher); @@ -95,17 +95,20 @@ module supra_framework::object_code_deployment { let code_signer = &object::generate_signer(constructor_ref); code::publish_package_txn(code_signer, metadata_serialized, code); - event::emit(Publish { object_address: signer::address_of(code_signer), }); + event::emit(Publish { object_address: signer::address_of(code_signer) }); - move_to(code_signer, ManagingRefs { - extend_ref: object::generate_extend_ref(constructor_ref), - }); + move_to( + code_signer, + ManagingRefs { extend_ref: object::generate_extend_ref(constructor_ref) } + ); } inline fun object_seed(publisher: address): vector { let sequence_number = account::get_sequence_number(publisher) + 1; let seeds = vector[]; - vector::append(&mut seeds, bcs::to_bytes(&OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR)); + vector::append( + &mut seeds, bcs::to_bytes(&OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR) + ); vector::append(&mut seeds, bcs::to_bytes(&sequence_number)); seeds } @@ -118,30 +121,35 @@ module supra_framework::object_code_deployment { publisher: &signer, metadata_serialized: vector, code: vector>, - code_object: Object, + code_object: Object ) acquires ManagingRefs { let publisher_address = signer::address_of(publisher); assert!( object::is_owner(code_object, publisher_address), - error::permission_denied(ENOT_CODE_OBJECT_OWNER), + error::permission_denied(ENOT_CODE_OBJECT_OWNER) ); let code_object_address = object::object_address(&code_object); - assert!(exists(code_object_address), error::not_found(ECODE_OBJECT_DOES_NOT_EXIST)); + assert!( + exists(code_object_address), + error::not_found(ECODE_OBJECT_DOES_NOT_EXIST) + ); let extend_ref = &borrow_global(code_object_address).extend_ref; let code_signer = &object::generate_signer_for_extending(extend_ref); code::publish_package_txn(code_signer, metadata_serialized, code); - event::emit(Upgrade { object_address: signer::address_of(code_signer), }); + event::emit(Upgrade { object_address: signer::address_of(code_signer) }); } /// Make an existing upgradable package immutable. Once this is called, the package cannot be made upgradable again. /// Each `code_object` should only have one package, as one package is deployed per object in this module. /// Requires the `publisher` to be the owner of the `code_object`. - public entry fun freeze_code_object(publisher: &signer, code_object: Object) { + public entry fun freeze_code_object( + publisher: &signer, code_object: Object + ) { code::freeze_code_object(publisher, code_object); - event::emit(Freeze { object_address: object::object_address(&code_object), }); + event::emit(Freeze { object_address: object::object_address(&code_object) }); } } diff --git a/aptos-move/framework/supra-framework/sources/pbo_delegation_pool.move b/aptos-move/framework/supra-framework/sources/pbo_delegation_pool.move index 75127476a71af..2b6939cf626f5 100644 --- a/aptos-move/framework/supra-framework/sources/pbo_delegation_pool.move +++ b/aptos-move/framework/supra-framework/sources/pbo_delegation_pool.move @@ -277,11 +277,11 @@ module supra_framework::pbo_delegation_pool { /// Capability that represents ownership over privileged operations on the underlying stake pool. struct DelegationPoolOwnership has key, store { /// equal to address of the resource account owning the stake pool - pool_address: address, + pool_address: address } struct ObservedLockupCycle has copy, drop, store { - index: u64, + index: u64 } struct UnlockSchedule has copy, drop, store { @@ -299,11 +299,10 @@ module supra_framework::pbo_delegation_pool { // Last vesting period, 1-indexed. For example if 2 months have passed, the last vesting period, if distribution // was requested, would be 2. Default value is 0 which means there have been no vesting periods yet. last_unlock_period: u64, - cumulative_unlocked_fraction: FixedPoint64, + cumulative_unlocked_fraction: FixedPoint64 } struct DelegationPool has key { - multisig_admin: Option
, // Shares pool of `active` + `pending_active` stake active_shares: pool_u64::Pool, @@ -329,12 +328,12 @@ module supra_framework::pbo_delegation_pool { reactivate_stake_events: EventHandle, unlock_stake_events: EventHandle, withdraw_stake_events: EventHandle, - distribute_commission_events: EventHandle, + distribute_commission_events: EventHandle } struct VotingRecordKey has copy, drop, store { voter: address, - proposal_id: u64, + proposal_id: u64 } /// Track delgated voter of each delegator. @@ -349,7 +348,7 @@ module supra_framework::pbo_delegation_pool { // If != last_locked_until_secs, it means that a lockup period has passed. // This is slightly different from ObservedLockupCycle because ObservedLockupCycle cannot detect if a lockup // period is passed when there is no unlocking during the lockup period. - last_locked_until_secs: u64, + last_locked_until_secs: u64 } /// Track total voteing power of each voter. @@ -366,7 +365,7 @@ module supra_framework::pbo_delegation_pool { // If != last_locked_until_secs, it means that a lockup period has passed. // This is slightly different from ObservedLockupCycle because ObservedLockupCycle cannot detect if a lockup // period is passed when there is no unlocking during the lockup period. - last_locked_until_secs: u64, + last_locked_until_secs: u64 } /// Track governance information of a delegation(e.g. voter delegation/voting power calculation). @@ -382,48 +381,48 @@ module supra_framework::pbo_delegation_pool { create_proposal_events: EventHandle, // Note: a DelegateVotingPowerEvent event only means that the delegator tries to change its voter. The change // won't take effect until the next lockup period. - delegate_voting_power_events: EventHandle, + delegate_voting_power_events: EventHandle } struct BeneficiaryForOperator has key { - beneficiary_for_operator: address, + beneficiary_for_operator: address } struct NextCommissionPercentage has key { commission_percentage_next_lockup_cycle: u64, - effective_after_secs: u64, + effective_after_secs: u64 } struct AddStakeEvent has drop, store { pool_address: address, delegator_address: address, amount_added: u64, - add_stake_fee: u64, + add_stake_fee: u64 } struct ReactivateStakeEvent has drop, store { pool_address: address, delegator_address: address, - amount_reactivated: u64, + amount_reactivated: u64 } struct UnlockStakeEvent has drop, store { pool_address: address, delegator_address: address, - amount_unlocked: u64, + amount_unlocked: u64 } struct WithdrawStakeEvent has drop, store { pool_address: address, delegator_address: address, - amount_withdrawn: u64, + amount_withdrawn: u64 } struct DistributeCommissionEvent has drop, store { pool_address: address, operator: address, commission_active: u64, - commission_pending_inactive: u64, + commission_pending_inactive: u64 } #[event] @@ -432,14 +431,14 @@ module supra_framework::pbo_delegation_pool { operator: address, beneficiary: address, commission_active: u64, - commission_pending_inactive: u64, + commission_pending_inactive: u64 } #[event] struct DelegatorReplacemendEvent has drop, store { pool_address: address, old_delegator: address, - new_delegator: address, + new_delegator: address } struct VoteEvent has drop, store { @@ -447,33 +446,33 @@ module supra_framework::pbo_delegation_pool { proposal_id: u64, delegation_pool: address, num_votes: u64, - should_pass: bool, + should_pass: bool } struct CreateProposalEvent has drop, store { proposal_id: u64, voter: address, - delegation_pool: address, + delegation_pool: address } struct DelegateVotingPowerEvent has drop, store { pool_address: address, delegator: address, - voter: address, + voter: address } #[event] struct SetBeneficiaryForOperator has drop, store { operator: address, old_beneficiary: address, - new_beneficiary: address, + new_beneficiary: address } #[event] struct CommissionPercentageChange has drop, store { pool_address: address, owner: address, - commission_percentage_next_lockup_cycle: u64, + commission_percentage_next_lockup_cycle: u64 } #[view] @@ -498,8 +497,8 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return whether a delegation pool has already enabled partial govnernance voting. public fun partial_governance_voting_enabled(pool_address: address): bool { - exists(pool_address) && stake::get_delegated_voter(pool_address) == - pool_address + exists(pool_address) + && stake::get_delegated_voter(pool_address) == pool_address } #[view] @@ -511,14 +510,19 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return whether the commission percentage for the next lockup cycle is effective. - public fun is_next_commission_percentage_effective(pool_address: address): bool acquires NextCommissionPercentage { - exists(pool_address) && timestamp::now_seconds() >= borrow_global< - NextCommissionPercentage>(pool_address).effective_after_secs + public fun is_next_commission_percentage_effective( + pool_address: address + ): bool acquires NextCommissionPercentage { + exists(pool_address) + && timestamp::now_seconds() + >= borrow_global(pool_address).effective_after_secs } #[view] /// Return the operator commission percentage set on the delegation pool `pool_address`. - public fun operator_commission_percentage(pool_address: address): u64 acquires DelegationPool, NextCommissionPercentage { + public fun operator_commission_percentage( + pool_address: address + ): u64 acquires DelegationPool, NextCommissionPercentage { assert_delegation_pool_exists(pool_address); if (is_next_commission_percentage_effective(pool_address)) { operator_commission_percentage_next_lockup_cycle(pool_address) @@ -529,7 +533,9 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return the operator commission percentage for the next lockup cycle. - public fun operator_commission_percentage_next_lockup_cycle(pool_address: address): u64 acquires DelegationPool, NextCommissionPercentage { + public fun operator_commission_percentage_next_lockup_cycle( + pool_address: address + ): u64 acquires DelegationPool, NextCommissionPercentage { assert_delegation_pool_exists(pool_address); if (exists(pool_address)) { borrow_global(pool_address).commission_percentage_next_lockup_cycle @@ -542,7 +548,9 @@ module supra_framework::pbo_delegation_pool { /// Return the number of delegators owning active stake within `pool_address`. public fun shareholders_count_active_pool(pool_address: address): u64 acquires DelegationPool { assert_delegation_pool_exists(pool_address); - pool_u64::shareholders_count(&borrow_global(pool_address).active_shares) + pool_u64::shareholders_count( + &borrow_global(pool_address).active_shares + ) } #[view] @@ -556,31 +564,32 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return whether the given delegator has any withdrawable stake. If they recently requested to unlock /// some stake and the stake pool's lockup cycle has not ended, their coins are not withdrawable yet. - public fun get_pending_withdrawal(pool_address: address, delegator_address: address) - : (bool, u64) acquires DelegationPool { + public fun get_pending_withdrawal( + pool_address: address, delegator_address: address + ): (bool, u64) acquires DelegationPool { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); - let (lockup_cycle_ended, _, pending_inactive, _, commission_pending_inactive) = calculate_stake_pool_drift( - pool - ); + let (lockup_cycle_ended, _, pending_inactive, _, commission_pending_inactive) = + calculate_stake_pool_drift(pool); - let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(pool, - delegator_address); + let (withdrawal_exists, withdrawal_olc) = + pending_withdrawal_exists(pool, delegator_address); if (!withdrawal_exists) { // if no pending withdrawal, there is neither inactive nor pending_inactive stake - (false, 0) } else { + (false, 0) + } else { // delegator has either inactive or pending_inactive stake due to automatic withdrawals let inactive_shares = table::borrow(&pool.inactive_shares, withdrawal_olc); if (withdrawal_olc.index < pool.observed_lockup_cycle.index) { // if withdrawal's lockup cycle ended on delegation pool then it is inactive (true, pool_u64::balance(inactive_shares, delegator_address)) - } - else { + } else { pending_inactive = pool_u64::shares_to_amount_with_total_coins( inactive_shares, pool_u64::shares(inactive_shares, delegator_address), // exclude operator pending_inactive rewards not converted to shares yet - pending_inactive - commission_pending_inactive); + pending_inactive - commission_pending_inactive + ); // if withdrawal's lockup cycle ended ONLY on stake pool then it is also inactive (lockup_cycle_ended, pending_inactive) } @@ -590,39 +599,44 @@ module supra_framework::pbo_delegation_pool { #[view] /// Return total stake owned by `delegator_address` within delegation pool `pool_address` /// in each of its individual states: (`active`,`inactive`,`pending_inactive`) - public fun get_stake(pool_address: address, delegator_address: address): (u64, u64, u64) acquires DelegationPool, BeneficiaryForOperator { + public fun get_stake( + pool_address: address, delegator_address: address + ): (u64, u64, u64) acquires DelegationPool, BeneficiaryForOperator { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); let (lockup_cycle_ended, active, _, commission_active, commission_pending_inactive) = - calculate_stake_pool_drift(pool); + + calculate_stake_pool_drift(pool); let total_active_shares = pool_u64::total_shares(&pool.active_shares); - let delegator_active_shares = pool_u64::shares(&pool.active_shares, - delegator_address); + let delegator_active_shares = + pool_u64::shares(&pool.active_shares, delegator_address); let (_, _, pending_active, _) = stake::get_stake(pool_address); if (pending_active == 0) { // zero `pending_active` stake indicates that either there are no `add_stake` fees or // previous epoch has ended and should identify shares owning these fees as released - total_active_shares = total_active_shares - pool_u64::shares(&pool.active_shares, - NULL_SHAREHOLDER); + total_active_shares = total_active_shares + - pool_u64::shares(&pool.active_shares, NULL_SHAREHOLDER); if (delegator_address == NULL_SHAREHOLDER) { delegator_active_shares = 0 } }; - active = pool_u64::shares_to_amount_with_total_stats(&pool.active_shares, + active = pool_u64::shares_to_amount_with_total_stats( + &pool.active_shares, delegator_active_shares, // exclude operator active rewards not converted to shares yet - active - commission_active, total_active_shares); + active - commission_active, + total_active_shares + ); // get state and stake (0 if there is none) of the pending withdrawal - let (withdrawal_inactive, withdrawal_stake) = get_pending_withdrawal(pool_address, - delegator_address); + let (withdrawal_inactive, withdrawal_stake) = + get_pending_withdrawal(pool_address, delegator_address); // report non-active stakes accordingly to the state of the pending withdrawal - let (inactive, pending_inactive) = if (withdrawal_inactive) - (withdrawal_stake, 0) - else - (0, withdrawal_stake); + let (inactive, pending_inactive) = + if (withdrawal_inactive) (withdrawal_stake, 0) + else (0, withdrawal_stake); // should also include commission rewards in case of the operator account // operator rewards are actually used to buy shares which is introducing @@ -650,19 +664,21 @@ module supra_framework::pbo_delegation_pool { /// To mitigate this, some of the added stake is extracted and fed back into the pool as placeholder /// for the rewards the remaining stake would have earned if active: /// extracted-fee = (amount - extracted-fee) * reward-rate% * (100% - operator-commission%) - public fun get_add_stake_fee(pool_address: address, amount: u64): u64 acquires DelegationPool, NextCommissionPercentage { + public fun get_add_stake_fee( + pool_address: address, amount: u64 + ): u64 acquires DelegationPool, NextCommissionPercentage { if (stake::is_current_epoch_validator(pool_address)) { - let (rewards_rate, rewards_rate_denominator) = staking_config::get_reward_rate(&staking_config::get()); + let (rewards_rate, rewards_rate_denominator) = + staking_config::get_reward_rate(&staking_config::get()); if (rewards_rate_denominator > 0) { assert_delegation_pool_exists(pool_address); - rewards_rate = rewards_rate * (MAX_FEE - operator_commission_percentage( - pool_address - )); + rewards_rate = rewards_rate + * (MAX_FEE - operator_commission_percentage(pool_address)); rewards_rate_denominator = rewards_rate_denominator * MAX_FEE; ( - (((amount as u128) * (rewards_rate as u128)) / ((rewards_rate as u128) - + (rewards_rate_denominator as u128))) as u64 + (((amount as u128) * (rewards_rate as u128)) + / ((rewards_rate as u128) + (rewards_rate_denominator as u128))) as u64 ) } else { 0 } } else { 0 } @@ -673,23 +689,24 @@ module supra_framework::pbo_delegation_pool { /// the delegation pool, implicitly its stake pool, in the special case /// the validator had gone inactive before its lockup expired. public fun can_withdraw_pending_inactive(pool_address: address): bool { - stake::get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE && timestamp::now_seconds() - >= stake::get_lockup_secs(pool_address) + stake::get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE + && timestamp::now_seconds() >= stake::get_lockup_secs(pool_address) } #[view] /// Return the total voting power of a delegator in a delegation pool. This function syncs DelegationPool to the /// latest state. - public fun calculate_and_update_voter_total_voting_power(pool_address: address, voter: address) - : u64 acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public fun calculate_and_update_voter_total_voting_power( + pool_address: address, voter: address + ): u64 acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert_partial_governance_voting_enabled(pool_address); // Delegation pool need to be synced to explain rewards(which could change the coin amount) and // commission(which could cause share transfer). synchronize_delegation_pool(pool_address); let pool = borrow_global(pool_address); let governance_records = borrow_global_mut(pool_address); - let latest_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, voter); + let latest_delegated_votes = + update_and_borrow_mut_delegated_votes(pool, governance_records, voter); calculate_total_voting_power(pool, latest_delegated_votes) } @@ -700,11 +717,11 @@ module supra_framework::pbo_delegation_pool { pool_address: address, delegator_address: address ): address acquires DelegationPool, GovernanceRecords { assert_partial_governance_voting_enabled(pool_address); - calculate_and_update_delegator_voter_internal(borrow_global( - pool_address - ), + calculate_and_update_delegator_voter_internal( + borrow_global(pool_address), borrow_global_mut(pool_address), - delegator_address) + delegator_address + ) } #[view] @@ -738,56 +755,79 @@ module supra_framework::pbo_delegation_pool { unlock_numerators: vector, unlock_denominator: u64, unlock_start_time: u64, - unlock_duration: u64, + unlock_duration: u64 ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { //if there is an admin, it must be a multisig if (option::is_some
(&multisig_admin)) { // `ms_admin` is guaranteed to be NOT `@0x0` here let ms_admin = option::get_with_default
(&multisig_admin, @0x0); - assert!(ms_admin != @0x0, error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO)); - assert!(multisig_account::num_signatures_required(ms_admin) >= 2, - EADMIN_NOT_MULTISIG); + assert!( + ms_admin != @0x0, error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO) + ); + assert!( + multisig_account::num_signatures_required(ms_admin) >= 2, + EADMIN_NOT_MULTISIG + ); }; // fail if the length of delegator_address and principle_stake is not the same - assert!(vector::length(&delegator_address) == vector::length(&principle_stake), - error::invalid_argument(EVECTOR_LENGTH_NOT_SAME)); + assert!( + vector::length(&delegator_address) == vector::length(&principle_stake), + error::invalid_argument(EVECTOR_LENGTH_NOT_SAME) + ); //Delegation pool must be enabled - assert!(features::delegation_pools_enabled(), - error::invalid_state(EDELEGATION_POOLS_DISABLED)); + assert!( + features::delegation_pools_enabled(), + error::invalid_state(EDELEGATION_POOLS_DISABLED) + ); //Unlock start time can not be in the past - assert!(unlock_start_time >= timestamp::now_seconds(), - error::invalid_argument(ESTARTUP_TIME_IN_PAST)); + assert!( + unlock_start_time >= timestamp::now_seconds(), + error::invalid_argument(ESTARTUP_TIME_IN_PAST) + ); //Unlock duration can not be zero assert!(unlock_duration > 0, error::invalid_argument(EPERIOD_DURATION_IS_ZERO)); //Fraction denominator can not be zero assert!(unlock_denominator != 0, error::invalid_argument(EDENOMINATOR_IS_ZERO)); //Fraction numerators can not be empty - assert!(vector::length(&unlock_numerators) > 0, - error::invalid_argument(EEMPTY_UNLOCK_SCHEDULE)); + assert!( + vector::length(&unlock_numerators) > 0, + error::invalid_argument(EEMPTY_UNLOCK_SCHEDULE) + ); //Fraction numerators can not be zero - assert!(!vector::any(&unlock_numerators, |e| { *e == 0 }), - error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION)); + assert!( + !vector::any(&unlock_numerators, |e| { *e == 0 }), + error::invalid_argument(ESCHEDULE_WITH_ZERO_FRACTION) + ); let sum = vector::foldr(unlock_numerators, 0, |e, a| { e + a }); //Sum of numerators can not be greater than denominators - assert!(sum <= unlock_denominator, - error::invalid_argument(ENUMERATORS_GRATER_THAN_DENOMINATOR)); + assert!( + sum <= unlock_denominator, + error::invalid_argument(ENUMERATORS_GRATER_THAN_DENOMINATOR) + ); let owner_address = signer::address_of(owner); - assert!(!owner_cap_exists(owner_address), - error::already_exists(EOWNER_CAP_ALREADY_EXISTS)); - assert!(operator_commission_percentage <= MAX_FEE, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE)); + assert!( + !owner_cap_exists(owner_address), + error::already_exists(EOWNER_CAP_ALREADY_EXISTS) + ); + assert!( + operator_commission_percentage <= MAX_FEE, + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE) + ); let sum = vector::fold(principle_stake, 0, |a, e| { a + e }); // fail if the value of coin and the sum of principle_stake is not the same - assert!(coin::value(&coin) == sum, - error::invalid_state(ECOIN_VALUE_NOT_SAME_AS_PRINCIPAL_STAKE)); + assert!( + coin::value(&coin) == sum, + error::invalid_state(ECOIN_VALUE_NOT_SAME_AS_PRINCIPAL_STAKE) + ); // generate a seed to be used to create the resource account hosting the delegation pool let seed = create_resource_account_seed(delegation_pool_creation_seed); - let (stake_pool_signer, stake_pool_signer_cap) = account::create_resource_account(owner, seed); + let (stake_pool_signer, stake_pool_signer_cap) = + account::create_resource_account(owner, seed); coin::register(&stake_pool_signer); // stake_pool_signer will be owner of the stake pool and have its `stake::OwnerCapability` @@ -796,9 +836,11 @@ module supra_framework::pbo_delegation_pool { coin::deposit(pool_address, coin); let inactive_shares = table::new(); - table::add(&mut inactive_shares, + table::add( + &mut inactive_shares, olc_with_index(0), - pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR)); + pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR) + ); let delegator_address_copy = copy delegator_address; let principle_stake_copy = copy principle_stake; @@ -813,14 +855,19 @@ module supra_framework::pbo_delegation_pool { //Create unlock schedule let schedule = vector::empty(); - vector::for_each_ref(&unlock_numerators, + vector::for_each_ref( + &unlock_numerators, |e| { - let fraction = fixed_point64::create_from_rational((*e as u128), - (unlock_denominator as u128)); + let fraction = + fixed_point64::create_from_rational( + (*e as u128), (unlock_denominator as u128) + ); vector::push_back(&mut schedule, fraction); - }); + } + ); - move_to(&stake_pool_signer, + move_to( + &stake_pool_signer, DelegationPool { multisig_admin: multisig_admin, active_shares: pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR), @@ -835,15 +882,27 @@ module supra_framework::pbo_delegation_pool { start_timestamp_secs: unlock_start_time, period_duration: unlock_duration, last_unlock_period: 0, - cumulative_unlocked_fraction: fixed_point64::create_from_rational(0, 1), + cumulative_unlocked_fraction: fixed_point64::create_from_rational( + 0, 1 + ) }, principle_stake: principle_stake_table, - add_stake_events: account::new_event_handle(&stake_pool_signer), - reactivate_stake_events: account::new_event_handle(&stake_pool_signer), - unlock_stake_events: account::new_event_handle(&stake_pool_signer), - withdraw_stake_events: account::new_event_handle(&stake_pool_signer), - distribute_commission_events: account::new_event_handle(&stake_pool_signer), - }); + add_stake_events: account::new_event_handle( + &stake_pool_signer + ), + reactivate_stake_events: account::new_event_handle( + &stake_pool_signer + ), + unlock_stake_events: account::new_event_handle( + &stake_pool_signer + ), + withdraw_stake_events: account::new_event_handle( + &stake_pool_signer + ), + distribute_commission_events: account::new_event_handle< + DistributeCommissionEvent>(&stake_pool_signer) + } + ); // save delegation pool ownership and resource account address (inner stake pool address) on `owner` move_to(owner, DelegationPoolOwnership { pool_address }); @@ -856,12 +915,16 @@ module supra_framework::pbo_delegation_pool { }; let (active_stake, _, _, _) = stake::get_stake(pool_address); // fail if coin in StakePool.active does not match with the balance in active_shares pool. - assert!(active_stake == pool_u64::total_coins(&borrow_global( - pool_address - ).active_shares), - error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL)); + assert!( + active_stake + == pool_u64::total_coins( + &borrow_global(pool_address).active_shares + ), + error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL) + ); // All delegation pool enable partial governace voting by default once the feature flag is enabled. - if (features::partial_governance_voting_enabled() && features::delegation_pool_partial_governance_voting_enabled()) { + if (features::partial_governance_voting_enabled() + && features::delegation_pool_partial_governance_voting_enabled()) { enable_partial_governance_voting(pool_address); } } @@ -876,16 +939,24 @@ module supra_framework::pbo_delegation_pool { public fun beneficiary_for_operator(operator: address): address acquires BeneficiaryForOperator { if (exists(operator)) { return borrow_global(operator).beneficiary_for_operator - } else { operator } + } else { + operator + } } /// Enable partial governance voting on a stake pool. The voter of this stake pool will be managed by this module. /// THe existing voter will be replaced. The function is permissionless. - public entry fun enable_partial_governance_voting(pool_address: address,) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { - assert!(features::partial_governance_voting_enabled(), - error::invalid_state(EDISABLED_FUNCTION)); - assert!(features::delegation_pool_partial_governance_voting_enabled(), - error::invalid_state(EDISABLED_FUNCTION)); + public entry fun enable_partial_governance_voting( + pool_address: address + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + assert!( + features::partial_governance_voting_enabled(), + error::invalid_state(EDISABLED_FUNCTION) + ); + assert!( + features::delegation_pool_partial_governance_voting_enabled(), + error::invalid_state(EDISABLED_FUNCTION) + ); assert_delegation_pool_exists(pool_address); // synchronize delegation and stake pools before any user operation. synchronize_delegation_pool(pool_address); @@ -894,19 +965,25 @@ module supra_framework::pbo_delegation_pool { let stake_pool_signer = retrieve_stake_pool_owner(delegation_pool); // delegated_voter is managed by the stake pool itself, which signer capability is managed by DelegationPool. // So voting power of this stake pool can only be used through this module. - stake::set_delegated_voter(&stake_pool_signer, - signer::address_of(&stake_pool_signer)); + stake::set_delegated_voter( + &stake_pool_signer, signer::address_of(&stake_pool_signer) + ); - move_to(&stake_pool_signer, + move_to( + &stake_pool_signer, GovernanceRecords { votes: smart_table::new(), votes_per_proposal: smart_table::new(), vote_delegation: smart_table::new(), delegated_votes: smart_table::new(), vote_events: account::new_event_handle(&stake_pool_signer), - create_proposal_events: account::new_event_handle(&stake_pool_signer), - delegate_voting_power_events: account::new_event_handle(&stake_pool_signer), - }); + create_proposal_events: account::new_event_handle( + &stake_pool_signer + ), + delegate_voting_power_events: account::new_event_handle< + DelegateVotingPowerEvent>(&stake_pool_signer) + } + ); } fun assert_owner_cap_exists(owner: address) { @@ -914,35 +991,52 @@ module supra_framework::pbo_delegation_pool { } fun assert_delegation_pool_exists(pool_address: address) { - assert!(delegation_pool_exists(pool_address), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST)); + assert!( + delegation_pool_exists(pool_address), + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + ); } - fun assert_min_active_balance(pool: &DelegationPool, delegator_address: address) { + fun assert_min_active_balance( + pool: &DelegationPool, delegator_address: address + ) { let balance = pool_u64::balance(&pool.active_shares, delegator_address); - assert!(balance >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW)); + assert!( + balance >= MIN_COINS_ON_SHARES_POOL, + error::invalid_argument(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW) + ); } - fun assert_min_pending_inactive_balance(pool: &DelegationPool, delegator_address: address) { - let balance = pool_u64::balance(pending_inactive_shares_pool(pool), - delegator_address); - assert!(balance >= MIN_COINS_ON_SHARES_POOL, - error::invalid_argument(EDELEGATOR_PENDING_INACTIVE_BALANCE_TOO_LOW)); + fun assert_min_pending_inactive_balance( + pool: &DelegationPool, delegator_address: address + ) { + let balance = + pool_u64::balance(pending_inactive_shares_pool(pool), delegator_address); + assert!( + balance >= MIN_COINS_ON_SHARES_POOL, + error::invalid_argument(EDELEGATOR_PENDING_INACTIVE_BALANCE_TOO_LOW) + ); } fun assert_partial_governance_voting_enabled(pool_address: address) { assert_delegation_pool_exists(pool_address); - assert!(partial_governance_voting_enabled(pool_address), - error::invalid_state(EPARTIAL_GOVERNANCE_VOTING_NOT_ENABLED)); + assert!( + partial_governance_voting_enabled(pool_address), + error::invalid_state(EPARTIAL_GOVERNANCE_VOTING_NOT_ENABLED) + ); } fun coins_to_redeem_to_ensure_min_stake( - src_shares_pool: &pool_u64::Pool, shareholder: address, amount: u64, + src_shares_pool: &pool_u64::Pool, + shareholder: address, + amount: u64 ): u64 { // find how many coins would be redeemed if supplying `amount` - let redeemed_coins = pool_u64::shares_to_amount(src_shares_pool, - amount_to_shares_to_redeem(src_shares_pool, shareholder, amount)); + let redeemed_coins = + pool_u64::shares_to_amount( + src_shares_pool, + amount_to_shares_to_redeem(src_shares_pool, shareholder, amount) + ); // if balance drops under threshold then redeem it entirely let src_balance = pool_u64::balance(src_shares_pool, shareholder); if (src_balance - redeemed_coins < MIN_COINS_ON_SHARES_POOL) { @@ -955,11 +1049,14 @@ module supra_framework::pbo_delegation_pool { src_shares_pool: &pool_u64::Pool, dst_shares_pool: &pool_u64::Pool, shareholder: address, - amount: u64, + amount: u64 ): u64 { // find how many coins would be redeemed from source if supplying `amount` - let redeemed_coins = pool_u64::shares_to_amount(src_shares_pool, - amount_to_shares_to_redeem(src_shares_pool, shareholder, amount)); + let redeemed_coins = + pool_u64::shares_to_amount( + src_shares_pool, + amount_to_shares_to_redeem(src_shares_pool, shareholder, amount) + ); // if balance on destination would be less than threshold then redeem difference to threshold let dst_balance = pool_u64::balance(dst_shares_pool, shareholder); if (dst_balance + redeemed_coins < MIN_COINS_ON_SHARES_POOL) { @@ -982,12 +1079,16 @@ module supra_framework::pbo_delegation_pool { } /// Get the active share amount of the delegator. - fun get_delegator_active_shares(pool: &DelegationPool, delegator: address): u128 { + fun get_delegator_active_shares( + pool: &DelegationPool, delegator: address + ): u128 { pool_u64::shares(&pool.active_shares, delegator) } /// Get the pending inactive share amount of the delegator. - fun get_delegator_pending_inactive_shares(pool: &DelegationPool, delegator: address): u128 { + fun get_delegator_pending_inactive_shares( + pool: &DelegationPool, delegator: address + ): u128 { pool_u64::shares(pending_inactive_shares_pool(pool), delegator) } @@ -996,12 +1097,14 @@ module supra_framework::pbo_delegation_pool { governance_records: &GovernanceRecords, voter: address, proposal_id: u64 ): u64 { let votes = &governance_records.votes; - let key = VotingRecordKey { voter, proposal_id, }; + let key = VotingRecordKey { voter, proposal_id }; *smart_table::borrow_with_default(votes, key, &0) } /// Create the seed to derive the resource account address. - fun create_resource_account_seed(delegation_pool_creation_seed: vector,): vector { + fun create_resource_account_seed( + delegation_pool_creation_seed: vector + ): vector { let seed = vector::empty(); // include module salt (before any subseeds) to avoid conflicts with other modules creating resource accounts vector::append(&mut seed, MODULE_SALT); @@ -1015,13 +1118,15 @@ module supra_framework::pbo_delegation_pool { governance_records: &mut GovernanceRecords, voter: address, proposal_id: u64 ): &mut u64 { let votes = &mut governance_records.votes; - let key = VotingRecordKey { proposal_id, voter, }; + let key = VotingRecordKey { proposal_id, voter }; smart_table::borrow_mut_with_default(votes, key, 0) } /// Update VoteDelegation of a delegator to up-to-date then borrow_mut it. fun update_and_borrow_mut_delegator_vote_delegation( - pool: &DelegationPool, governance_records: &mut GovernanceRecords, delegator: address + pool: &DelegationPool, + governance_records: &mut GovernanceRecords, + delegator: address ): &mut VoteDelegation { let pool_address = get_pool_address(pool); let locked_until_secs = stake::get_lockup_secs(pool_address); @@ -1030,20 +1135,21 @@ module supra_framework::pbo_delegation_pool { // By default, a delegator's delegated voter is itself. // TODO: recycle storage when VoteDelegation equals to default value. if (!smart_table::contains(vote_delegation_table, delegator)) { - return smart_table::borrow_mut_with_default(vote_delegation_table, + return smart_table::borrow_mut_with_default( + vote_delegation_table, delegator, VoteDelegation { voter: delegator, last_locked_until_secs: locked_until_secs, - pending_voter: delegator, + pending_voter: delegator } ) }; let vote_delegation = smart_table::borrow_mut(vote_delegation_table, delegator); // A lockup period has passed since last time `vote_delegation` was updated. Pending voter takes effect. - if (vote_delegation.last_locked_until_secs < locked_until_secs && vote_delegation.voter != vote_delegation - .pending_voter) { + if (vote_delegation.last_locked_until_secs < locked_until_secs + && vote_delegation.voter != vote_delegation.pending_voter) { vote_delegation.voter = vote_delegation.pending_voter; }; vote_delegation @@ -1062,13 +1168,14 @@ module supra_framework::pbo_delegation_pool { if (!smart_table::contains(delegated_votes_per_voter, voter)) { let active_shares = get_delegator_active_shares(pool, voter); let inactive_shares = get_delegator_pending_inactive_shares(pool, voter); - return smart_table::borrow_mut_with_default(delegated_votes_per_voter, + return smart_table::borrow_mut_with_default( + delegated_votes_per_voter, voter, DelegatedVotes { active_shares, pending_inactive_shares: inactive_shares, active_shares_next_lockup: active_shares, - last_locked_until_secs: locked_until_secs, + last_locked_until_secs: locked_until_secs } ) }; @@ -1092,20 +1199,28 @@ module supra_framework::pbo_delegation_pool { fun calculate_total_voting_power( delegation_pool: &DelegationPool, latest_delegated_votes: &DelegatedVotes ): u64 { - let active_amount = pool_u64::shares_to_amount(&delegation_pool.active_shares, - latest_delegated_votes.active_shares); - let pending_inactive_amount = pool_u64::shares_to_amount( - pending_inactive_shares_pool(delegation_pool), - latest_delegated_votes.pending_inactive_shares); + let active_amount = + pool_u64::shares_to_amount( + &delegation_pool.active_shares, latest_delegated_votes.active_shares + ); + let pending_inactive_amount = + pool_u64::shares_to_amount( + pending_inactive_shares_pool(delegation_pool), + latest_delegated_votes.pending_inactive_shares + ); active_amount + pending_inactive_amount } /// Update VoteDelegation of a delegator to up-to-date then return the latest voter. fun calculate_and_update_delegator_voter_internal( - pool: &DelegationPool, governance_records: &mut GovernanceRecords, delegator: address + pool: &DelegationPool, + governance_records: &mut GovernanceRecords, + delegator: address ): address { - let vote_delegation = update_and_borrow_mut_delegator_vote_delegation(pool, - governance_records, delegator); + let vote_delegation = + update_and_borrow_mut_delegator_vote_delegation( + pool, governance_records, delegator + ); vote_delegation.voter } @@ -1113,61 +1228,83 @@ module supra_framework::pbo_delegation_pool { fun calculate_and_update_delegated_votes( pool: &DelegationPool, governance_records: &mut GovernanceRecords, voter: address ): u64 { - let delegated_votes = update_and_borrow_mut_delegated_votes(pool, governance_records, - voter); + let delegated_votes = + update_and_borrow_mut_delegated_votes(pool, governance_records, voter); calculate_total_voting_power(pool, delegated_votes) } /// Allows an owner to change the operator of the underlying stake pool. - public entry fun set_operator(owner: &signer, new_operator: address) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun set_operator( + owner: &signer, new_operator: address + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { let pool_address = get_owned_pool_address(signer::address_of(owner)); // synchronize delegation and stake pools before any user operation // ensure the old operator is paid its uncommitted commission rewards synchronize_delegation_pool(pool_address); - stake::set_operator(&retrieve_stake_pool_owner(borrow_global( - pool_address - )), new_operator); + stake::set_operator( + &retrieve_stake_pool_owner(borrow_global(pool_address)), + new_operator + ); } /// Allows an operator to change its beneficiary. Any existing unpaid commission rewards will be paid to the new /// beneficiary. To ensures payment to the current beneficiary, one should first call `synchronize_delegation_pool` /// before switching the beneficiary. An operator can set one beneficiary for delegation pools, not a separate /// one for each pool. - public entry fun set_beneficiary_for_operator(operator: &signer, new_beneficiary: address) acquires BeneficiaryForOperator { - assert!(features::operator_beneficiary_change_enabled(), - std::error::invalid_state(EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED)); + public entry fun set_beneficiary_for_operator( + operator: &signer, new_beneficiary: address + ) acquires BeneficiaryForOperator { + assert!( + features::operator_beneficiary_change_enabled(), + std::error::invalid_state(EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED) + ); // The beneficiay address of an operator is stored under the operator's address. // So, the operator does not need to be validated with respect to a staking pool. let operator_addr = signer::address_of(operator); let old_beneficiary = beneficiary_for_operator(operator_addr); if (exists(operator_addr)) { borrow_global_mut(operator_addr).beneficiary_for_operator = - new_beneficiary; + new_beneficiary; } else { - move_to(operator, BeneficiaryForOperator { - beneficiary_for_operator: new_beneficiary - }); + move_to( + operator, + BeneficiaryForOperator { beneficiary_for_operator: new_beneficiary } + ); }; - emit(SetBeneficiaryForOperator { + emit( + SetBeneficiaryForOperator { operator: operator_addr, old_beneficiary, - new_beneficiary, - }); + new_beneficiary + } + ); } /// Allows an owner to update the commission percentage for the operator of the underlying stake pool. - public entry fun update_commission_percentage(owner: &signer, new_commission_percentage: u64) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { - assert!(features::commission_change_delegation_pool_enabled(), - error::invalid_state(ECOMMISSION_RATE_CHANGE_NOT_SUPPORTED)); - assert!(new_commission_percentage <= MAX_FEE, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE)); + public entry fun update_commission_percentage( + owner: &signer, new_commission_percentage: u64 + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + assert!( + features::commission_change_delegation_pool_enabled(), + error::invalid_state(ECOMMISSION_RATE_CHANGE_NOT_SUPPORTED) + ); + assert!( + new_commission_percentage <= MAX_FEE, + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE) + ); let owner_address = signer::address_of(owner); let pool_address = get_owned_pool_address(owner_address); - assert!(operator_commission_percentage(pool_address) + MAX_COMMISSION_INCREASE >= new_commission_percentage, - error::invalid_argument(ETOO_LARGE_COMMISSION_INCREASE)); - assert!(stake::get_remaining_lockup_secs(pool_address) >= min_remaining_secs_for_commission_change(), - error::invalid_state(ETOO_LATE_COMMISSION_CHANGE)); + assert!( + operator_commission_percentage(pool_address) + MAX_COMMISSION_INCREASE + >= new_commission_percentage, + error::invalid_argument(ETOO_LARGE_COMMISSION_INCREASE) + ); + assert!( + stake::get_remaining_lockup_secs(pool_address) + >= min_remaining_secs_for_commission_change(), + error::invalid_state(ETOO_LATE_COMMISSION_CHANGE) + ); // synchronize delegation and stake pools before any user operation. this ensures: // (1) the operator is paid its uncommitted commission rewards with the old commission percentage, and @@ -1175,41 +1312,52 @@ module supra_framework::pbo_delegation_pool { synchronize_delegation_pool(pool_address); if (exists(pool_address)) { - let commission_percentage = borrow_global_mut( - pool_address - ); + let commission_percentage = + borrow_global_mut(pool_address); commission_percentage.commission_percentage_next_lockup_cycle = new_commission_percentage; commission_percentage.effective_after_secs = stake::get_lockup_secs( pool_address ); } else { let delegation_pool = borrow_global(pool_address); - let pool_signer = account::create_signer_with_capability(&delegation_pool.stake_pool_signer_cap); - move_to(&pool_signer, + let pool_signer = + account::create_signer_with_capability( + &delegation_pool.stake_pool_signer_cap + ); + move_to( + &pool_signer, NextCommissionPercentage { commission_percentage_next_lockup_cycle: new_commission_percentage, - effective_after_secs: stake::get_lockup_secs(pool_address), - }); + effective_after_secs: stake::get_lockup_secs(pool_address) + } + ); }; - event::emit(CommissionPercentageChange { + event::emit( + CommissionPercentageChange { pool_address, owner: owner_address, - commission_percentage_next_lockup_cycle: new_commission_percentage, - }); + commission_percentage_next_lockup_cycle: new_commission_percentage + } + ); } /// Allows an owner to change the delegated voter of the underlying stake pool. - public entry fun set_delegated_voter(owner: &signer, new_voter: address) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun set_delegated_voter( + owner: &signer, new_voter: address + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { // No one can change delegated_voter once the partial governance voting feature is enabled. - assert!(!features::delegation_pool_partial_governance_voting_enabled(), - error::invalid_state(EDEPRECATED_FUNCTION)); + assert!( + !features::delegation_pool_partial_governance_voting_enabled(), + error::invalid_state(EDEPRECATED_FUNCTION) + ); let pool_address = get_owned_pool_address(signer::address_of(owner)); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); - stake::set_delegated_voter(&retrieve_stake_pool_owner(borrow_global( - pool_address - )), new_voter); + stake::set_delegated_voter( + &retrieve_stake_pool_owner(borrow_global(pool_address)), + new_voter + ); } /// Allows a delegator to delegate its voting power to a voter. If this delegator already has a delegated voter, @@ -1225,41 +1373,48 @@ module supra_framework::pbo_delegation_pool { let delegator_address = signer::address_of(delegator); let delegation_pool = borrow_global(pool_address); let governance_records = borrow_global_mut(pool_address); - let delegator_vote_delegation = update_and_borrow_mut_delegator_vote_delegation( - delegation_pool, governance_records, delegator_address - ); + let delegator_vote_delegation = + update_and_borrow_mut_delegator_vote_delegation( + delegation_pool, governance_records, delegator_address + ); let pending_voter: address = delegator_vote_delegation.pending_voter; // No need to update if the voter doesn't really change. if (pending_voter != new_voter) { delegator_vote_delegation.pending_voter = new_voter; - let active_shares = get_delegator_active_shares(delegation_pool, - delegator_address); + let active_shares = + get_delegator_active_shares(delegation_pool, delegator_address); // of -= // of += - let pending_delegated_votes = update_and_borrow_mut_delegated_votes( - delegation_pool, governance_records, pending_voter - ); + let pending_delegated_votes = + update_and_borrow_mut_delegated_votes( + delegation_pool, governance_records, pending_voter + ); pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup - active_shares; - let new_delegated_votes = update_and_borrow_mut_delegated_votes(delegation_pool, - governance_records, new_voter); + let new_delegated_votes = + update_and_borrow_mut_delegated_votes( + delegation_pool, governance_records, new_voter + ); new_delegated_votes.active_shares_next_lockup = new_delegated_votes.active_shares_next_lockup + active_shares; }; - event::emit_event(&mut governance_records.delegate_voting_power_events, + event::emit_event( + &mut governance_records.delegate_voting_power_events, DelegateVotingPowerEvent { pool_address, delegator: delegator_address, - voter: new_voter, + voter: new_voter } ); } /// Add `amount` of coins to the delegation pool `pool_address` during initialization of pool. - fun add_stake_initialization(delegator_address: address, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords { + fun add_stake_initialization( + delegator_address: address, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords { // short-circuit if amount to add is 0 so no event is emitted if (amount == 0) { return }; @@ -1272,7 +1427,9 @@ module supra_framework::pbo_delegation_pool { } /// Add `amount` of coins to the delegation pool `pool_address`. - public entry fun add_stake(delegator: &signer, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun add_stake( + delegator: &signer, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { // short-circuit if amount to add is 0 so no event is emitted if (amount == 0) { return }; // synchronize delegation and stake pools before any user operation @@ -1298,18 +1455,21 @@ module supra_framework::pbo_delegation_pool { // in order to appreciate all shares on the active pool atomically buy_in_active_shares(pool, NULL_SHAREHOLDER, add_stake_fee); - event::emit_event(&mut pool.add_stake_events, + event::emit_event( + &mut pool.add_stake_events, AddStakeEvent { pool_address, delegator_address, amount_added: amount, - add_stake_fee, - }, + add_stake_fee + } ); } fun replace_in_smart_tables( - table: &mut SmartTable, old_entry: Key, new_entry: Key + table: &mut SmartTable, + old_entry: Key, + new_entry: Key ) { if (smart_table::contains(table, old_entry)) { let val = smart_table::remove(table, old_entry); @@ -1322,43 +1482,62 @@ module supra_framework::pbo_delegation_pool { /// owner of `new_delegator` , Only for those stakeholders which were added at the time of creation /// This does not apply to anyone who added stake later or operator public entry fun replace_delegator( - multisig_admin: &signer, pool_address: address, old_delegator: address, new_delegator: address + multisig_admin: &signer, + pool_address: address, + old_delegator: address, + new_delegator: address ) acquires DelegationPool, GovernanceRecords { //Ensure replacement address is different - assert!(old_delegator != new_delegator, - error::invalid_argument(ENEW_IS_SAME_AS_OLD_DELEGATOR)); + assert!( + old_delegator != new_delegator, + error::invalid_argument(ENEW_IS_SAME_AS_OLD_DELEGATOR) + ); //Ensure it is a valid `pool_addres` - assert!(exists(pool_address), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST)); + assert!( + exists(pool_address), + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + ); let pool: &mut DelegationPool = borrow_global_mut(pool_address); let admin_addr = signer::address_of(multisig_admin); //Ensure that authorized admin is calling - assert!(admin_addr != @0x0, error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO)); - assert!(admin_addr == option::get_with_default(&pool.multisig_admin, @0x0), - error::permission_denied(ENOT_AUTHORIZED)); + assert!( + admin_addr != @0x0, error::invalid_argument(EADMIN_ADDRESS_CANNOT_BE_ZERO) + ); + assert!( + admin_addr == option::get_with_default(&pool.multisig_admin, @0x0), + error::permission_denied(ENOT_AUTHORIZED) + ); //Ensure `old_delegator` is part of original principle stakers before commencing the replacement - assert!(table::contains(&pool.principle_stake, old_delegator), - error::unavailable(EDELEGATOR_DOES_NOT_EXIST)); + assert!( + table::contains(&pool.principle_stake, old_delegator), + error::unavailable(EDELEGATOR_DOES_NOT_EXIST) + ); //replace in `active_shares` pool { let active_pool = &mut pool.active_shares; let active_shares = pool_u64::shares(active_pool, old_delegator); - pool_u64::transfer_shares(active_pool, old_delegator, new_delegator, - active_shares); + pool_u64::transfer_shares( + active_pool, old_delegator, new_delegator, active_shares + ); }; //replace in `inactive_shares` pool - let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(pool, - old_delegator); + let (withdrawal_exists, withdrawal_olc) = + pending_withdrawal_exists(pool, old_delegator); if (withdrawal_exists) { - let inactive_pool = table::borrow_mut(&mut pool.inactive_shares, withdrawal_olc); + let inactive_pool = + table::borrow_mut(&mut pool.inactive_shares, withdrawal_olc); let inactive_shares = pool_u64::shares(inactive_pool, old_delegator); - pool_u64::transfer_shares(inactive_pool, old_delegator, new_delegator, - inactive_shares); + pool_u64::transfer_shares( + inactive_pool, + old_delegator, + new_delegator, + inactive_shares + ); //replace in `pending_withdrawals` { @@ -1373,28 +1552,39 @@ module supra_framework::pbo_delegation_pool { { if (features::partial_governance_voting_enabled()) { let grecords = borrow_global_mut(pool_address); - replace_in_smart_tables(&mut grecords.vote_delegation, old_delegator, - new_delegator); - replace_in_smart_tables(&mut grecords.delegated_votes, old_delegator, - new_delegator); + replace_in_smart_tables( + &mut grecords.vote_delegation, old_delegator, new_delegator + ); + replace_in_smart_tables( + &mut grecords.delegated_votes, old_delegator, new_delegator + ); let old_keys: vector = vector::empty(); let new_keys: vector = vector::empty(); - smart_table::for_each_ref(&grecords.votes, + smart_table::for_each_ref( + &grecords.votes, |key, _val| { let VotingRecordKey { voter, proposal_id } = *key; if (voter == old_delegator) { - vector::push_back(&mut new_keys, VotingRecordKey { + vector::push_back( + &mut new_keys, + VotingRecordKey { voter: new_delegator, proposal_id: proposal_id - }); + } + ); vector::push_back(&mut old_keys, *key); }; - }); + } + ); - vector::zip_ref(&old_keys, &new_keys, |old, new| { + vector::zip_ref( + &old_keys, + &new_keys, + |old, new| { replace_in_smart_tables(&mut grecords.votes, *old, *new); - }); + } + ); } }; // replace in principle_stake table @@ -1403,7 +1593,9 @@ module supra_framework::pbo_delegation_pool { table::add(&mut pool.principle_stake, new_delegator, val); }; - event::emit(DelegatorReplacemendEvent { pool_address, old_delegator, new_delegator },); + event::emit( + DelegatorReplacemendEvent { pool_address, old_delegator, new_delegator } + ); } @@ -1411,58 +1603,81 @@ module supra_framework::pbo_delegation_pool { /// Provides how much amount is unlockable based on `principle_unlock_schedule.cumulative_unlocked_fraction` /// Note that `cumulative_unlocked_fraction` is not updated in this function so the information may not be /// accurate as time passes - public fun cached_unlockable_balance(delegator_addr: address, pool_addr: address): u64 acquires DelegationPool { - assert!(exists(pool_addr), - error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST)); + public fun cached_unlockable_balance( + delegator_addr: address, pool_addr: address + ): u64 acquires DelegationPool { + assert!( + exists(pool_addr), + error::invalid_argument(EDELEGATION_POOL_DOES_NOT_EXIST) + ); let pool = borrow_global(pool_addr); - let delegator_active_balance = pool_u64::balance(&pool.active_shares, delegator_addr); - let unlockable_fraction = pool.principle_unlock_schedule.cumulative_unlocked_fraction; - let delegator_principle_stake = *table::borrow(&pool.principle_stake, delegator_addr); + let delegator_active_balance = + pool_u64::balance(&pool.active_shares, delegator_addr); + let unlockable_fraction = + pool.principle_unlock_schedule.cumulative_unlocked_fraction; + let delegator_principle_stake = + *table::borrow(&pool.principle_stake, delegator_addr); //To avoid problem even if fraction is slightly above 1 - let unlockable_principle_stake = (math128::min(fixed_point64::multiply_u128( - (delegator_principle_stake as u128), unlockable_fraction - ), - (delegator_principle_stake as u128)) as u64); + let unlockable_principle_stake = + ( + math128::min( + fixed_point64::multiply_u128( + (delegator_principle_stake as u128), unlockable_fraction + ), + (delegator_principle_stake as u128) + ) as u64 + ); let locked_amount = delegator_principle_stake - unlockable_principle_stake; - assert!(delegator_active_balance >= locked_amount, - error::invalid_state(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW)); + assert!( + delegator_active_balance >= locked_amount, + error::invalid_state(EDELEGATOR_ACTIVE_BALANCE_TOO_LOW) + ); delegator_active_balance - locked_amount } - public fun can_principle_unlock(delegator_addr: address, pool_address: address, amount: u64) - : bool acquires DelegationPool { + public fun can_principle_unlock( + delegator_addr: address, pool_address: address, amount: u64 + ): bool acquires DelegationPool { - let principle_stake_table = &borrow_global(pool_address).principle_stake; + let principle_stake_table = + &borrow_global(pool_address).principle_stake; if (!table::contains(principle_stake_table, delegator_addr)) { return true }; - let unlock_schedule = &mut borrow_global_mut(pool_address).principle_unlock_schedule; + let unlock_schedule = + &mut borrow_global_mut(pool_address).principle_unlock_schedule; let one = fixed_point64::create_from_rational(1, 1); - if (fixed_point64::greater_or_equal(unlock_schedule.cumulative_unlocked_fraction, one)) { + if (fixed_point64::greater_or_equal( + unlock_schedule.cumulative_unlocked_fraction, one + )) { return true }; if (unlock_schedule.start_timestamp_secs > timestamp::now_seconds()) { - let unlockable_amount = cached_unlockable_balance(delegator_addr, pool_address); + let unlockable_amount = + cached_unlockable_balance(delegator_addr, pool_address); return amount <= unlockable_amount }; //subtraction safety due to check above - let unlock_periods_passed = (timestamp::now_seconds() - unlock_schedule.start_timestamp_secs) - / unlock_schedule.period_duration; + let unlock_periods_passed = + (timestamp::now_seconds() - unlock_schedule.start_timestamp_secs) + / unlock_schedule.period_duration; let last_unlocked_period = unlock_schedule.last_unlock_period; let schedule_length = vector::length(&unlock_schedule.schedule); let cfraction = unlock_schedule.cumulative_unlocked_fraction; - while (last_unlocked_period < unlock_periods_passed && fixed_point64::less( - cfraction, one - )) { - let next_fraction = if (schedule_length <= last_unlocked_period) { - *vector::borrow(&unlock_schedule.schedule, schedule_length - 1) - } else { *vector::borrow(&unlock_schedule.schedule, last_unlocked_period) }; + while (last_unlocked_period < unlock_periods_passed + && fixed_point64::less(cfraction, one)) { + let next_fraction = + if (schedule_length <= last_unlocked_period) { + *vector::borrow(&unlock_schedule.schedule, schedule_length - 1) + } else { + *vector::borrow(&unlock_schedule.schedule, last_unlocked_period) + }; cfraction = fixed_point64::add(cfraction, next_fraction); last_unlocked_period = last_unlocked_period + 1; @@ -1477,40 +1692,54 @@ module supra_framework::pbo_delegation_pool { /// Unlock `amount` from the active + pending_active stake of `delegator` or /// at most how much active stake there is on the stake pool. - public entry fun unlock(delegator: &signer, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun unlock( + delegator: &signer, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { // short-circuit if amount to unlock is 0 so no event is emitted if (amount == 0) { return }; // fail unlock of more stake than `active` on the stake pool let (active, _, _, _) = stake::get_stake(pool_address); - assert!(amount <= active, - error::invalid_argument(ENOT_ENOUGH_ACTIVE_STAKE_TO_UNLOCK)); + assert!( + amount <= active, error::invalid_argument(ENOT_ENOUGH_ACTIVE_STAKE_TO_UNLOCK) + ); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); let delegator_address = signer::address_of(delegator); // fail if the amount after withdraw is less than the principle stake and the lockup time is not expired - assert!(can_principle_unlock(delegator_address, pool_address, amount), - error::invalid_argument(EAMOUNT_REQUESTED_NOT_UNLOCKABLE)); + assert!( + can_principle_unlock(delegator_address, pool_address, amount), + error::invalid_argument(EAMOUNT_REQUESTED_NOT_UNLOCKABLE) + ); let pool = borrow_global_mut(pool_address); - amount = coins_to_transfer_to_ensure_min_stake(&pool.active_shares, - pending_inactive_shares_pool(pool), delegator_address, amount,); + amount = coins_to_transfer_to_ensure_min_stake( + &pool.active_shares, + pending_inactive_shares_pool(pool), + delegator_address, + amount + ); amount = redeem_active_shares(pool, delegator_address, amount); stake::unlock(&retrieve_stake_pool_owner(pool), amount); buy_in_pending_inactive_shares(pool, delegator_address, amount); assert_min_pending_inactive_balance(pool, delegator_address); - event::emit_event(&mut pool.unlock_stake_events, - UnlockStakeEvent { pool_address, delegator_address, amount_unlocked: amount, }, + event::emit_event( + &mut pool.unlock_stake_events, + UnlockStakeEvent { pool_address, delegator_address, amount_unlocked: amount } ); let (active_stake, _, pending_active, _) = stake::get_stake(pool_address); - assert!(active_stake + pending_active == pool_u64::total_coins(&pool.active_shares), - error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL)); + assert!( + active_stake + pending_active == pool_u64::total_coins(&pool.active_shares), + error::invalid_state(EACTIVE_COIN_VALUE_NOT_SAME_STAKE_DELEGATION_POOL) + ); } /// Move `amount` of coins from pending_inactive to active. - public entry fun reactivate_stake(delegator: &signer, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun reactivate_stake( + delegator: &signer, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { // short-circuit if amount to reactivate is 0 so no event is emitted if (amount == 0) { return }; // synchronize delegation and stake pools before any user operation @@ -1519,48 +1748,71 @@ module supra_framework::pbo_delegation_pool { let pool = borrow_global_mut(pool_address); let delegator_address = signer::address_of(delegator); - amount = coins_to_transfer_to_ensure_min_stake(pending_inactive_shares_pool(pool), &pool - .active_shares, delegator_address, amount,); + amount = coins_to_transfer_to_ensure_min_stake( + pending_inactive_shares_pool(pool), + &pool.active_shares, + delegator_address, + amount + ); let observed_lockup_cycle = pool.observed_lockup_cycle; - amount = redeem_inactive_shares(pool, delegator_address, amount, - observed_lockup_cycle); + amount = redeem_inactive_shares( + pool, delegator_address, amount, observed_lockup_cycle + ); stake::reactivate_stake(&retrieve_stake_pool_owner(pool), amount); buy_in_active_shares(pool, delegator_address, amount); assert_min_active_balance(pool, delegator_address); - event::emit_event(&mut pool.reactivate_stake_events, - ReactivateStakeEvent { pool_address, delegator_address, amount_reactivated: amount, }, + event::emit_event( + &mut pool.reactivate_stake_events, + ReactivateStakeEvent { + pool_address, + delegator_address, + amount_reactivated: amount + } ); } /// Withdraw `amount` of owned inactive stake from the delegation pool at `pool_address`. - public entry fun withdraw(delegator: &signer, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun withdraw( + delegator: &signer, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert!(amount > 0, error::invalid_argument(EWITHDRAW_ZERO_STAKE)); // synchronize delegation and stake pools before any user operation synchronize_delegation_pool(pool_address); - withdraw_internal(borrow_global_mut(pool_address), - signer::address_of(delegator), amount); + withdraw_internal( + borrow_global_mut(pool_address), + signer::address_of(delegator), + amount + ); } - fun withdraw_internal(pool: &mut DelegationPool, delegator_address: address, amount: u64) acquires GovernanceRecords { + fun withdraw_internal( + pool: &mut DelegationPool, delegator_address: address, amount: u64 + ) acquires GovernanceRecords { // TODO: recycle storage when a delegator fully exits the delegation pool. // short-circuit if amount to withdraw is 0 so no event is emitted if (amount == 0) { return }; let pool_address = get_pool_address(pool); - let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(pool, - delegator_address); + let (withdrawal_exists, withdrawal_olc) = + pending_withdrawal_exists(pool, delegator_address); // exit if no withdrawal or (it is pending and cannot withdraw pending_inactive stake from stake pool) - if (!(withdrawal_exists - && (withdrawal_olc.index < pool.observed_lockup_cycle.index || can_withdraw_pending_inactive( - pool_address - )))) { return }; + if (!( + withdrawal_exists + && ( + withdrawal_olc.index < pool.observed_lockup_cycle.index + || can_withdraw_pending_inactive(pool_address) + ) + )) { return }; if (withdrawal_olc.index == pool.observed_lockup_cycle.index) { - amount = coins_to_redeem_to_ensure_min_stake(pending_inactive_shares_pool(pool), - delegator_address, amount,) + amount = coins_to_redeem_to_ensure_min_stake( + pending_inactive_shares_pool(pool), + delegator_address, + amount + ) }; amount = redeem_inactive_shares(pool, delegator_address, amount, withdrawal_olc); @@ -1591,20 +1843,27 @@ module supra_framework::pbo_delegation_pool { let (_, inactive, _, _) = stake::get_stake(pool_address); pool.total_coins_inactive = inactive; - event::emit_event(&mut pool.withdraw_stake_events, - WithdrawStakeEvent { pool_address, delegator_address, amount_withdrawn: amount, }, + event::emit_event( + &mut pool.withdraw_stake_events, + WithdrawStakeEvent { + pool_address, + delegator_address, + amount_withdrawn: amount + } ); } /// Return the unique observed lockup cycle where delegator `delegator_address` may have /// unlocking (or already unlocked) stake to be withdrawn from delegation pool `pool`. /// A bool is returned to signal if a pending withdrawal exists at all. - fun pending_withdrawal_exists(pool: &DelegationPool, delegator_address: address) - : (bool, - ObservedLockupCycle) { + fun pending_withdrawal_exists( + pool: &DelegationPool, delegator_address: address + ): (bool, ObservedLockupCycle) { if (table::contains(&pool.pending_withdrawals, delegator_address)) { (true, *table::borrow(&pool.pending_withdrawals, delegator_address)) - } else { (false, olc_with_index(0)) } + } else { + (false, olc_with_index(0)) + } } /// Return a mutable reference to the shares pool of `pending_inactive` stake on the @@ -1622,18 +1881,24 @@ module supra_framework::pbo_delegation_pool { /// if existing and already inactive to allow the creation of a new one. /// `pending_inactive` stake would be left untouched even if withdrawable and should /// be explicitly withdrawn by delegator - fun execute_pending_withdrawal(pool: &mut DelegationPool, delegator_address: address) acquires GovernanceRecords { - let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(pool, - delegator_address); - if (withdrawal_exists && withdrawal_olc.index < pool.observed_lockup_cycle.index) { + fun execute_pending_withdrawal( + pool: &mut DelegationPool, delegator_address: address + ) acquires GovernanceRecords { + let (withdrawal_exists, withdrawal_olc) = + pending_withdrawal_exists(pool, delegator_address); + if (withdrawal_exists + && withdrawal_olc.index < pool.observed_lockup_cycle.index) { withdraw_internal(pool, delegator_address, MAX_U64); } } /// Buy shares into the active pool on behalf of delegator `shareholder` who /// deposited `coins_amount`. This function doesn't make any coin transfer. - fun buy_in_active_shares(pool: &mut DelegationPool, shareholder: address, coins_amount: u64,) - : u128 acquires GovernanceRecords { + fun buy_in_active_shares( + pool: &mut DelegationPool, + shareholder: address, + coins_amount: u64 + ): u128 acquires GovernanceRecords { let new_shares = pool_u64::amount_to_shares(&pool.active_shares, coins_amount); // No need to buy 0 shares. if (new_shares == 0) { @@ -1643,8 +1908,9 @@ module supra_framework::pbo_delegation_pool { // Always update governance records before any change to the shares pool. let pool_address = get_pool_address(pool); if (partial_governance_voting_enabled(pool_address)) { - update_governance_records_for_buy_in_active_shares(pool, pool_address, - new_shares, shareholder); + update_governance_records_for_buy_in_active_shares( + pool, pool_address, new_shares, shareholder + ); }; pool_u64::buy_in(&mut pool.active_shares, shareholder, coins_amount); @@ -1656,10 +1922,14 @@ module supra_framework::pbo_delegation_pool { /// If delegator's pending withdrawal exists and has been inactivated, execute it firstly /// to ensure there is always only one withdrawal request. fun buy_in_pending_inactive_shares( - pool: &mut DelegationPool, shareholder: address, coins_amount: u64, + pool: &mut DelegationPool, + shareholder: address, + coins_amount: u64 ): u128 acquires GovernanceRecords { - let new_shares = pool_u64::amount_to_shares(pending_inactive_shares_pool(pool), - coins_amount); + let new_shares = + pool_u64::amount_to_shares( + pending_inactive_shares_pool(pool), coins_amount + ); // never create a new pending withdrawal unless delegator owns some pending_inactive shares if (new_shares == 0) { return 0 @@ -1668,21 +1938,27 @@ module supra_framework::pbo_delegation_pool { // Always update governance records before any change to the shares pool. let pool_address = get_pool_address(pool); if (partial_governance_voting_enabled(pool_address)) { - update_governance_records_for_buy_in_pending_inactive_shares(pool, pool_address, - new_shares, shareholder); + update_governance_records_for_buy_in_pending_inactive_shares( + pool, pool_address, new_shares, shareholder + ); }; // cannot buy inactive shares, only pending_inactive at current lockup cycle - pool_u64::buy_in(pending_inactive_shares_pool_mut(pool), shareholder, coins_amount); + pool_u64::buy_in( + pending_inactive_shares_pool_mut(pool), shareholder, coins_amount + ); // execute the pending withdrawal if exists and is inactive before creating a new one execute_pending_withdrawal(pool, shareholder); // save observed lockup cycle for the new pending withdrawal let observed_lockup_cycle = pool.observed_lockup_cycle; - assert!(*table::borrow_mut_with_default(&mut pool.pending_withdrawals, shareholder, - observed_lockup_cycle) == observed_lockup_cycle, - error::invalid_state(EPENDING_WITHDRAWAL_EXISTS)); + assert!( + *table::borrow_mut_with_default( + &mut pool.pending_withdrawals, shareholder, observed_lockup_cycle + ) == observed_lockup_cycle, + error::invalid_state(EPENDING_WITHDRAWAL_EXISTS) + ); new_shares } @@ -1690,7 +1966,9 @@ module supra_framework::pbo_delegation_pool { /// Convert `coins_amount` of coins to be redeemed from shares pool `shares_pool` /// to the exact number of shares to redeem in order to achieve this. fun amount_to_shares_to_redeem( - shares_pool: &pool_u64::Pool, shareholder: address, coins_amount: u64, + shares_pool: &pool_u64::Pool, + shareholder: address, + coins_amount: u64 ): u128 { if (coins_amount >= pool_u64::balance(shares_pool, shareholder)) { // cap result at total shares of shareholder to pass `EINSUFFICIENT_SHARES` on subsequent redeem @@ -1704,18 +1982,22 @@ module supra_framework::pbo_delegation_pool { /// wants to unlock `coins_amount` of its active stake. /// Extracted coins will be used to buy shares into the pending_inactive pool and /// be available for withdrawal when current OLC ends. - fun redeem_active_shares(pool: &mut DelegationPool, shareholder: address, coins_amount: u64,) - : u64 acquires GovernanceRecords { - let shares_to_redeem = amount_to_shares_to_redeem(&pool.active_shares, shareholder, - coins_amount); + fun redeem_active_shares( + pool: &mut DelegationPool, + shareholder: address, + coins_amount: u64 + ): u64 acquires GovernanceRecords { + let shares_to_redeem = + amount_to_shares_to_redeem(&pool.active_shares, shareholder, coins_amount); // silently exit if not a shareholder otherwise redeem would fail with `ESHAREHOLDER_NOT_FOUND` if (shares_to_redeem == 0) return 0; // Always update governance records before any change to the shares pool. let pool_address = get_pool_address(pool); if (partial_governance_voting_enabled(pool_address)) { - update_governanace_records_for_redeem_active_shares(pool, pool_address, - shares_to_redeem, shareholder); + update_governanace_records_for_redeem_active_shares( + pool, pool_address, shares_to_redeem, shareholder + ); }; pool_u64::redeem_shares(&mut pool.active_shares, shareholder, shares_to_redeem) @@ -1731,26 +2013,31 @@ module supra_framework::pbo_delegation_pool { pool: &mut DelegationPool, shareholder: address, coins_amount: u64, - lockup_cycle: ObservedLockupCycle, + lockup_cycle: ObservedLockupCycle ): u64 acquires GovernanceRecords { - let shares_to_redeem = amount_to_shares_to_redeem(table::borrow(&pool.inactive_shares, - lockup_cycle), shareholder, coins_amount); + let shares_to_redeem = + amount_to_shares_to_redeem( + table::borrow(&pool.inactive_shares, lockup_cycle), + shareholder, + coins_amount + ); // silently exit if not a shareholder otherwise redeem would fail with `ESHAREHOLDER_NOT_FOUND` if (shares_to_redeem == 0) return 0; // Always update governance records before any change to the shares pool. let pool_address = get_pool_address(pool); // Only redeem shares from the pending_inactive pool at `lockup_cycle` == current OLC. - if (partial_governance_voting_enabled(pool_address) && lockup_cycle.index == pool.observed_lockup_cycle - .index) { - update_governanace_records_for_redeem_pending_inactive_shares(pool, pool_address, - shares_to_redeem, shareholder); + if (partial_governance_voting_enabled(pool_address) + && lockup_cycle.index == pool.observed_lockup_cycle.index) { + update_governanace_records_for_redeem_pending_inactive_shares( + pool, pool_address, shares_to_redeem, shareholder + ); }; let inactive_shares = table::borrow_mut(&mut pool.inactive_shares, lockup_cycle); // 1. reaching here means delegator owns inactive/pending_inactive shares at OLC `lockup_cycle` - let redeemed_coins = pool_u64::redeem_shares(inactive_shares, shareholder, - shares_to_redeem); + let redeemed_coins = + pool_u64::redeem_shares(inactive_shares, shareholder, shares_to_redeem); // if entirely reactivated pending_inactive stake or withdrawn inactive one, // re-enable unlocking for delegator by deleting this pending withdrawal @@ -1760,8 +2047,11 @@ module supra_framework::pbo_delegation_pool { table::remove(&mut pool.pending_withdrawals, shareholder); }; // destroy inactive shares pool of past OLC if all its stake has been withdrawn - if (lockup_cycle.index < pool.observed_lockup_cycle.index && total_coins(inactive_shares) == 0) { - pool_u64::destroy_empty(table::remove(&mut pool.inactive_shares, lockup_cycle)); + if (lockup_cycle.index < pool.observed_lockup_cycle.index + && total_coins(inactive_shares) == 0) { + pool_u64::destroy_empty( + table::remove(&mut pool.inactive_shares, lockup_cycle) + ); }; redeemed_coins @@ -1771,10 +2061,12 @@ module supra_framework::pbo_delegation_pool { /// capture the rewards earned in the meantime, resulted operator commission and /// whether the lockup expired on the stake pool. fun calculate_stake_pool_drift(pool: &DelegationPool): (bool, u64, u64, u64, u64) { - let (active, inactive, pending_active, pending_inactive) = stake::get_stake( - get_pool_address(pool)); - assert!(inactive >= pool.total_coins_inactive, - error::invalid_state(ESLASHED_INACTIVE_STAKE_ON_PAST_OLC)); + let (active, inactive, pending_active, pending_inactive) = + stake::get_stake(get_pool_address(pool)); + assert!( + inactive >= pool.total_coins_inactive, + error::invalid_state(ESLASHED_INACTIVE_STAKE_ON_PAST_OLC) + ); // determine whether a new lockup cycle has been ended on the stake pool and // inactivated SOME `pending_inactive` stake which should stop earning rewards now, // thus requiring separation of the `pending_inactive` stake on current observed lockup @@ -1797,32 +2089,52 @@ module supra_framework::pbo_delegation_pool { // operator `active` rewards not persisted yet to the active shares pool let pool_active = total_coins(&pool.active_shares); - let commission_active = if (active > pool_active) { - math64::mul_div(active - pool_active, pool.operator_commission_percentage, - MAX_FEE) - } else { - // handle any slashing applied to `active` stake - 0 }; + let commission_active = + if (active > pool_active) { + math64::mul_div( + active - pool_active, pool.operator_commission_percentage, MAX_FEE + ) + } else { + // handle any slashing applied to `active` stake + 0 + }; // operator `pending_inactive` rewards not persisted yet to the pending_inactive shares pool let pool_pending_inactive = total_coins(pending_inactive_shares_pool(pool)); - let commission_pending_inactive = if (pending_inactive > pool_pending_inactive) { - math64::mul_div(pending_inactive - pool_pending_inactive, pool.operator_commission_percentage, - MAX_FEE) - } else { - // handle any slashing applied to `pending_inactive` stake - 0 }; + let commission_pending_inactive = + if (pending_inactive > pool_pending_inactive) { + math64::mul_div( + pending_inactive - pool_pending_inactive, + pool.operator_commission_percentage, + MAX_FEE + ) + } else { + // handle any slashing applied to `pending_inactive` stake + 0 + }; - (lockup_cycle_ended, active, pending_inactive, commission_active, - commission_pending_inactive) + ( + lockup_cycle_ended, + active, + pending_inactive, + commission_active, + commission_pending_inactive + ) } /// Synchronize delegation and stake pools: distribute yet-undetected rewards to the corresponding internal /// shares pools, assign commission to operator and eventually prepare delegation pool for a new lockup cycle. - public entry fun synchronize_delegation_pool(pool_address: address) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun synchronize_delegation_pool( + pool_address: address + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { assert_delegation_pool_exists(pool_address); let pool = borrow_global_mut(pool_address); - let (lockup_cycle_ended, active, pending_inactive, commission_active, - commission_pending_inactive) = calculate_stake_pool_drift(pool); + let ( + lockup_cycle_ended, + active, + pending_inactive, + commission_active, + commission_pending_inactive + ) = calculate_stake_pool_drift(pool); // zero `pending_active` stake indicates that either there are no `add_stake` fees or // previous epoch has ended and should release the shares owning the existing fees @@ -1839,35 +2151,49 @@ module supra_framework::pbo_delegation_pool { // update total coins accumulated by `active` + `pending_active` shares // redeemed `add_stake` fees are restored and distributed to the rest of the pool as rewards - pool_u64::update_total_coins(&mut pool.active_shares, active - commission_active); + pool_u64::update_total_coins(&mut pool.active_shares, active + - commission_active); // update total coins accumulated by `pending_inactive` shares at current observed lockup cycle - pool_u64::update_total_coins(pending_inactive_shares_pool_mut(pool), - pending_inactive - commission_pending_inactive); + pool_u64::update_total_coins( + pending_inactive_shares_pool_mut(pool), + pending_inactive - commission_pending_inactive + ); // reward operator its commission out of uncommitted active rewards (`add_stake` fees already excluded) - buy_in_active_shares(pool, - beneficiary_for_operator(stake::get_operator(pool_address)), commission_active); + buy_in_active_shares( + pool, + beneficiary_for_operator(stake::get_operator(pool_address)), + commission_active + ); // reward operator its commission out of uncommitted pending_inactive rewards - buy_in_pending_inactive_shares(pool, + buy_in_pending_inactive_shares( + pool, beneficiary_for_operator(stake::get_operator(pool_address)), - commission_pending_inactive); + commission_pending_inactive + ); - event::emit_event(&mut pool.distribute_commission_events, + event::emit_event( + &mut pool.distribute_commission_events, DistributeCommissionEvent { pool_address, operator: stake::get_operator(pool_address), commission_active, - commission_pending_inactive, - },); + commission_pending_inactive + } + ); if (features::operator_beneficiary_change_enabled()) { - emit(DistributeCommission { + emit( + DistributeCommission { pool_address, operator: stake::get_operator(pool_address), - beneficiary: beneficiary_for_operator(stake::get_operator(pool_address)), + beneficiary: beneficiary_for_operator( + stake::get_operator(pool_address) + ), commission_active, - commission_pending_inactive, - }) + commission_pending_inactive + } + ) }; // advance lockup cycle on delegation pool if already ended on stake pool (AND stake explicitly inactivated) @@ -1879,9 +2205,11 @@ module supra_framework::pbo_delegation_pool { // advance lockup cycle on the delegation pool pool.observed_lockup_cycle.index = pool.observed_lockup_cycle.index + 1; // start new lockup cycle with a fresh shares pool for `pending_inactive` stake - table::add(&mut pool.inactive_shares, + table::add( + &mut pool.inactive_shares, pool.observed_lockup_cycle, - pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR)); + pool_u64::create_with_scaling_factor(SHARES_SCALING_FACTOR) + ); }; if (is_next_commission_percentage_effective(pool_address)) { @@ -1892,81 +2220,115 @@ module supra_framework::pbo_delegation_pool { } fun update_governance_records_for_buy_in_active_shares( - pool: &DelegationPool, pool_address: address, new_shares: u128, shareholder: address + pool: &DelegationPool, + pool_address: address, + new_shares: u128, + shareholder: address ) acquires GovernanceRecords { // of += ----> // of += // of += let governance_records = borrow_global_mut(pool_address); - let vote_delegation = update_and_borrow_mut_delegator_vote_delegation(pool, - governance_records, shareholder); + let vote_delegation = + update_and_borrow_mut_delegator_vote_delegation( + pool, governance_records, shareholder + ); let current_voter = vote_delegation.voter; let pending_voter = vote_delegation.pending_voter; - let current_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, current_voter); - current_delegated_votes.active_shares = current_delegated_votes.active_shares + new_shares; + let current_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); + current_delegated_votes.active_shares = current_delegated_votes.active_shares + + new_shares; if (pending_voter == current_voter) { current_delegated_votes.active_shares_next_lockup = current_delegated_votes.active_shares_next_lockup + new_shares; } else { - let pending_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, pending_voter); + let pending_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, pending_voter + ); pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup + new_shares; }; } fun update_governance_records_for_buy_in_pending_inactive_shares( - pool: &DelegationPool, pool_address: address, new_shares: u128, shareholder: address + pool: &DelegationPool, + pool_address: address, + new_shares: u128, + shareholder: address ) acquires GovernanceRecords { // of += ----> // of += // no impact on of let governance_records = borrow_global_mut(pool_address); - let current_voter = calculate_and_update_delegator_voter_internal(pool, - governance_records, shareholder); - let current_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, current_voter); + let current_voter = + calculate_and_update_delegator_voter_internal( + pool, governance_records, shareholder + ); + let current_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); current_delegated_votes.pending_inactive_shares = current_delegated_votes.pending_inactive_shares + new_shares; } fun update_governanace_records_for_redeem_active_shares( - pool: &DelegationPool, pool_address: address, shares_to_redeem: u128, shareholder: address + pool: &DelegationPool, + pool_address: address, + shares_to_redeem: u128, + shareholder: address ) acquires GovernanceRecords { // of -= ----> // of -= // of -= let governance_records = borrow_global_mut(pool_address); - let vote_delegation = update_and_borrow_mut_delegator_vote_delegation(pool, - governance_records, shareholder); + let vote_delegation = + update_and_borrow_mut_delegator_vote_delegation( + pool, governance_records, shareholder + ); let current_voter = vote_delegation.voter; let pending_voter = vote_delegation.pending_voter; - let current_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, current_voter); - current_delegated_votes.active_shares = current_delegated_votes.active_shares - shares_to_redeem; + let current_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); + current_delegated_votes.active_shares = current_delegated_votes.active_shares + - shares_to_redeem; if (current_voter == pending_voter) { current_delegated_votes.active_shares_next_lockup = current_delegated_votes.active_shares_next_lockup - shares_to_redeem; } else { - let pending_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, pending_voter); + let pending_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, pending_voter + ); pending_delegated_votes.active_shares_next_lockup = pending_delegated_votes.active_shares_next_lockup - shares_to_redeem; }; } fun update_governanace_records_for_redeem_pending_inactive_shares( - pool: &DelegationPool, pool_address: address, shares_to_redeem: u128, shareholder: address + pool: &DelegationPool, + pool_address: address, + shares_to_redeem: u128, + shareholder: address ) acquires GovernanceRecords { // of -= ----> // of -= // no impact on of let governance_records = borrow_global_mut(pool_address); - let current_voter = calculate_and_update_delegator_voter_internal(pool, - governance_records, shareholder); - let current_delegated_votes = update_and_borrow_mut_delegated_votes(pool, - governance_records, current_voter); + let current_voter = + calculate_and_update_delegator_voter_internal( + pool, governance_records, shareholder + ); + let current_delegated_votes = + update_and_borrow_mut_delegated_votes( + pool, governance_records, current_voter + ); current_delegated_votes.pending_inactive_shares = current_delegated_votes.pending_inactive_shares - shares_to_redeem; } @@ -2025,14 +2387,30 @@ module supra_framework::pbo_delegation_pool { #[test_only] public fun initialize_for_test(supra_framework: &signer) { - initialize_for_test_custom(supra_framework, 100 * ONE_SUPRA, 100000000000 * ONE_SUPRA, - LOCKUP_CYCLE_SECONDS, true, 1, 100, 1000000); + initialize_for_test_custom( + supra_framework, + 100 * ONE_SUPRA, + 100000000000 * ONE_SUPRA, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 1000000 + ); } #[test_only] public fun initialize_for_test_no_reward(supra_framework: &signer) { - initialize_for_test_custom(supra_framework, 100 * ONE_SUPRA, 10000000 * ONE_SUPRA, - LOCKUP_CYCLE_SECONDS, true, 0, 100, 1000000); + initialize_for_test_custom( + supra_framework, + 100 * ONE_SUPRA, + 10000000 * ONE_SUPRA, + LOCKUP_CYCLE_SECONDS, + true, + 0, + 100, + 1000000 + ); } #[test_only] @@ -2044,26 +2422,30 @@ module supra_framework::pbo_delegation_pool { allow_validator_set_change: bool, rewards_rate_numerator: u64, rewards_rate_denominator: u64, - voting_power_increase_limit: u64, + voting_power_increase_limit: u64 ) { account::create_account_for_test(signer::address_of(supra_framework)); - stake::initialize_for_test_custom(supra_framework, + stake::initialize_for_test_custom( + supra_framework, minimum_stake, maximum_stake, recurring_lockup_secs, allow_validator_set_change, rewards_rate_numerator, rewards_rate_denominator, - voting_power_increase_limit, + voting_power_increase_limit ); reconfiguration::initialize_for_test(supra_framework); - features::change_feature_flags_for_testing(supra_framework, + features::change_feature_flags_for_testing( + supra_framework, vector[ DELEGATION_POOLS, MODULE_EVENT, OPERATOR_BENEFICIARY_CHANGE, - COMMISSION_CHANGE_DELEGATION_POOL], - vector[]); + COMMISSION_CHANGE_DELEGATION_POOL + ], + vector[] + ); } #[test_only] @@ -2087,7 +2469,8 @@ module supra_framework::pbo_delegation_pool { account::create_account_for_test(validator_address); }; - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, multisig_admin, commission_percentage, vector::empty(), @@ -2097,7 +2480,8 @@ module supra_framework::pbo_delegation_pool { unlock_numerators, unlock_denominator, principle_lockup_time, - unlock_duration); + unlock_duration + ); let pool_address = get_owned_pool_address(validator_address); stake::rotate_consensus_key(validator, pool_address, CONSENSUS_KEY_1); @@ -2117,7 +2501,9 @@ module supra_framework::pbo_delegation_pool { } #[test_only] - fun unlock_with_min_stake_disabled(delegator: &signer, pool_address: address, amount: u64) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + fun unlock_with_min_stake_disabled( + delegator: &signer, pool_address: address, amount: u64 + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { synchronize_delegation_pool(pool_address); let pool = borrow_global_mut(pool_address); @@ -2130,15 +2516,20 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x3000A, location = Self)] - public entry fun test_delegation_pools_disabled(supra_framework: &signer, validator: &signer,) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_delegation_pools_disabled( + supra_framework: &signer, validator: &signer + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - features::change_feature_flags_for_testing(supra_framework, vector[], vector[DELEGATION_POOLS]); + features::change_feature_flags_for_testing( + supra_framework, vector[], vector[DELEGATION_POOLS] + ); - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 0, vector::empty(), @@ -2148,12 +2539,13 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12) + 12 + ) } #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_set_operator_and_delegated_voter( - supra_framework: &signer, validator: &signer, + supra_framework: &signer, validator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; @@ -2161,7 +2553,8 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; let validator_address = signer::address_of(validator); - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 0, vector::empty(), @@ -2171,7 +2564,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(validator_address); assert!(stake::get_operator(pool_address) == @0x123, 1); @@ -2186,7 +2580,9 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x60001, location = Self)] - public entry fun test_cannot_set_operator(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_cannot_set_operator( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); // account does not own any delegation pool set_operator(validator, @0x111); @@ -2194,7 +2590,9 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x60001, location = Self)] - public entry fun test_cannot_set_delegated_voter(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_cannot_set_delegated_voter( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); // account does not own any delegation pool set_delegated_voter(validator, @0x112); @@ -2202,13 +2600,16 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x80002, location = Self)] - public entry fun test_already_owns_delegation_pool(supra_framework: &signer, validator: &signer,) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_already_owns_delegation_pool( + supra_framework: &signer, validator: &signer + ) acquires DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 0, x"00", @@ -2218,9 +2619,11 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let coin = stake::mint_coins(100 * ONE_SUPRA); - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 0, x"01", @@ -2230,18 +2633,22 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, 0, - 12); + 12 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000B, location = Self)] - public entry fun test_cannot_withdraw_zero_stake(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_cannot_withdraw_zero_stake( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 0, x"00", @@ -2251,19 +2658,23 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); withdraw(validator, get_owned_pool_address(signer::address_of(validator)), 0); } #[test(supra_framework = @supra_framework, validator = @0x123)] - public entry fun test_initialize_delegation_pool(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_initialize_delegation_pool( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[]; let principle_stake = vector[]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; let validator_address = signer::address_of(validator); - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 1234, vector::empty(), @@ -2273,7 +2684,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); assert_owner_cap_exists(validator_address); let pool_address = get_owned_pool_address(validator_address); @@ -2290,15 +2702,30 @@ module supra_framework::pbo_delegation_pool { stake::assert_stake_pool(pool_address, 0, 0, 0, 0); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_add_stake_fee( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { - initialize_for_test_custom(supra_framework, 100 * ONE_SUPRA, 10000000 * ONE_SUPRA, - LOCKUP_CYCLE_SECONDS, true, 1, 100, 1000000); + initialize_for_test_custom( + supra_framework, + 100 * ONE_SUPRA, + 10000000 * ONE_SUPRA, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 1000000 + ); let delegator_address = vector[@0x010, @0x020]; let principle_stake = vector[0, 0]; let coin = stake::mint_coins(0); @@ -2307,7 +2734,8 @@ module supra_framework::pbo_delegation_pool { account::create_account_for_test(validator_address); // create delegation pool with 37.35% operator commission - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 3735, vector::empty(), @@ -2317,7 +2745,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(validator_address); stake::rotate_consensus_key(validator, pool_address, CONSENSUS_KEY_1); @@ -2358,8 +2787,13 @@ module supra_framework::pbo_delegation_pool { add_stake(delegator1, pool_address, 10000 * ONE_SUPRA); let fee = get_add_stake_fee(pool_address, 10000 * ONE_SUPRA); - assert_delegation(delegator1_address, pool_address, delegator1_active + 10000 * ONE_SUPRA - - fee, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + delegator1_active + 10000 * ONE_SUPRA - fee, + 0, + 0 + ); // delegator 2 should not benefit in any way from this new stake assert_delegation(delegator2_address, pool_address, 1000000000000, 0, 0); @@ -2393,72 +2827,92 @@ module supra_framework::pbo_delegation_pool { add_stake(delegator1, pool_address, 20000 * ONE_SUPRA); fee = get_add_stake_fee(pool_address, 20000 * ONE_SUPRA); - assert_delegation(delegator1_address, pool_address, delegator1_active + 20000 * ONE_SUPRA - - fee, 0, 0); + assert_delegation( + delegator1_address, + pool_address, + delegator1_active + 20000 * ONE_SUPRA - fee, + 0, + 0 + ); // delegator 1 unlocks his entire newly added stake unlock(delegator1, pool_address, 20000 * ONE_SUPRA - fee); end_aptos_epoch(); // delegator 1 should own previous 11131957502250 active * 1.006265 and 20000 coins pending_inactive - assert_delegation(delegator1_address, pool_address, 11201699216002, 0, - 2000000000000); + assert_delegation( + delegator1_address, pool_address, 11201699216002, 0, 2000000000000 + ); // stakes should remain the same - `Self::get_stake` correctly calculates them synchronize_delegation_pool(pool_address); - assert_delegation(delegator1_address, pool_address, 11201699216002, 0, - 2000000000000); + assert_delegation( + delegator1_address, pool_address, 11201699216002, 0, 2000000000000 + ); let reward_period_start_time_in_sec = timestamp::now_seconds(); // Enable rewards rate decrease. Initially rewards rate is still 1% every epoch. Rewards rate halves every year. let one_year_in_secs: u64 = 31536000; - staking_config::initialize_rewards(supra_framework, + staking_config::initialize_rewards( + supra_framework, fixed_point64::create_from_rational(2, 100), fixed_point64::create_from_rational(6, 1000), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(50, 100),); - features::change_feature_flags_for_testing(supra_framework, vector[features::get_periodical_reward_rate_decrease_feature()], - vector[]); + fixed_point64::create_from_rational(50, 100) + ); + features::change_feature_flags_for_testing( + supra_framework, + vector[features::get_periodical_reward_rate_decrease_feature()], + vector[] + ); // add more stake from delegator 1 stake::mint(delegator1, 20000 * ONE_SUPRA); let delegator1_pending_inactive: u64; - (delegator1_active, _, delegator1_pending_inactive) = get_stake(pool_address, - delegator1_address); + (delegator1_active, _, delegator1_pending_inactive) = get_stake( + pool_address, delegator1_address + ); fee = get_add_stake_fee(pool_address, 20000 * ONE_SUPRA); add_stake(delegator1, pool_address, 20000 * ONE_SUPRA); - assert_delegation(delegator1_address, + assert_delegation( + delegator1_address, pool_address, delegator1_active + 20000 * ONE_SUPRA - fee, 0, - delegator1_pending_inactive); + delegator1_pending_inactive + ); // delegator 1 unlocks his entire newly added stake unlock(delegator1, pool_address, 20000 * ONE_SUPRA - fee); end_aptos_epoch(); // delegator 1 should own previous 11201699216002 active * ~1.01253 and 20000 * ~1.01253 + 20000 coins pending_inactive - assert_delegation(delegator1_address, pool_address, 11342056366822, 0, - 4025059974939); + assert_delegation( + delegator1_address, pool_address, 11342056366822, 0, 4025059974939 + ); // stakes should remain the same - `Self::get_stake` correctly calculates them synchronize_delegation_pool(pool_address); - assert_delegation(delegator1_address, pool_address, 11342056366822, 0, - 4025059974939); + assert_delegation( + delegator1_address, pool_address, 11342056366822, 0, 4025059974939 + ); fast_forward_seconds(one_year_in_secs); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_never_create_pending_withdrawal_if_no_shares_bought( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[0 * ONE_SUPRA]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, false, @@ -2470,7 +2924,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -2527,13 +2982,16 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10008, location = Self)] - public entry fun test_add_stake_min_amount(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_add_stake_min_amount( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, MIN_COINS_ON_SHARES_POOL - 1, false, false, @@ -2545,17 +3003,21 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] - public entry fun test_add_stake_single(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_add_stake_single( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[]; let principle_stake = vector[]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, false, false, @@ -2567,7 +3029,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -2585,7 +3048,9 @@ module supra_framework::pbo_delegation_pool { add_stake(validator, pool_address, 250 * ONE_SUPRA); // check added stake have been transferred out of delegator account - assert!(coin::balance(validator_address) == balance - 250 * ONE_SUPRA, 0); + assert!( + coin::balance(validator_address) == balance - 250 * ONE_SUPRA, 0 + ); // zero `add_stake` fee charged from added stake assert_delegation(validator_address, pool_address, 1250 * ONE_SUPRA, 0, 0); // zero `add_stake` fee transferred to null shareholder @@ -2612,8 +3077,13 @@ module supra_framework::pbo_delegation_pool { add_stake(validator, pool_address, 100 * ONE_SUPRA); let fee2 = get_add_stake_fee(pool_address, 100 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 1600 * ONE_SUPRA - fee1 - fee2, 0, - 0); + assert_delegation( + validator_address, + pool_address, + 1600 * ONE_SUPRA - fee1 - fee2, + 0, + 0 + ); // check `add_stake` fee has been transferred to the null shareholder assert_delegation(NULL_SHAREHOLDER, pool_address, fee1 + fee2, 0, 0); stake::assert_stake_pool(pool_address, 1250 * ONE_SUPRA, 0, 350 * ONE_SUPRA, 0); @@ -2626,9 +3096,13 @@ module supra_framework::pbo_delegation_pool { // check that shares of null shareholder have been released assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); synchronize_delegation_pool(pool_address); - assert!(pool_u64::shares(&borrow_global(pool_address).active_shares, - NULL_SHAREHOLDER) == 0, - 0); + assert!( + pool_u64::shares( + &borrow_global(pool_address).active_shares, + NULL_SHAREHOLDER + ) == 0, + 0 + ); assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); // add 200 coins being pending_active until next epoch @@ -2649,22 +3123,29 @@ module supra_framework::pbo_delegation_pool { // check that shares of null shareholder have been released assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); synchronize_delegation_pool(pool_address); - assert!(pool_u64::shares(&borrow_global(pool_address).active_shares, - NULL_SHAREHOLDER) == 0, - 0); + assert!( + pool_u64::shares( + &borrow_global(pool_address).active_shares, + NULL_SHAREHOLDER + ) == 0, + 0 + ); assert_delegation(NULL_SHAREHOLDER, pool_address, 0, 0, 0); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_add_stake_many( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -2676,7 +3157,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -2733,14 +3215,17 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_unlock_single( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address_vec = vector[@0x010]; let principle_stake = vector[0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 100 * ONE_SUPRA, true, true, @@ -2752,7 +3237,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -2770,17 +3256,35 @@ module supra_framework::pbo_delegation_pool { // cannot unlock pending_active stake (only 100/300 stake can be displaced) unlock(validator, pool_address, 100 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 200 * ONE_SUPRA - fee, 0, 100 * ONE_SUPRA); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, 100 * ONE_SUPRA); + assert_delegation( + validator_address, + pool_address, + 200 * ONE_SUPRA - fee, + 0, + 100 * ONE_SUPRA + ); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, false, 100 * ONE_SUPRA + ); stake::assert_stake_pool(pool_address, 0, 0, 200 * ONE_SUPRA, 100 * ONE_SUPRA); assert_inactive_shares_pool(pool_address, 0, true, 100 * ONE_SUPRA); // reactivate entire pending_inactive stake progressively reactivate_stake(validator, pool_address, 50 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 250 * ONE_SUPRA - fee, 0, 50 * ONE_SUPRA); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, 50 * ONE_SUPRA); - stake::assert_stake_pool(pool_address, 50 * ONE_SUPRA, 0, 200 * ONE_SUPRA, 50 * ONE_SUPRA); + assert_delegation( + validator_address, + pool_address, + 250 * ONE_SUPRA - fee, + 0, + 50 * ONE_SUPRA + ); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, false, 50 * ONE_SUPRA + ); + stake::assert_stake_pool( + pool_address, 50 * ONE_SUPRA, 0, 200 * ONE_SUPRA, 50 * ONE_SUPRA + ); reactivate_stake(validator, pool_address, 50 * ONE_SUPRA); @@ -2799,18 +3303,23 @@ module supra_framework::pbo_delegation_pool { unlock(validator, pool_address, 150 * ONE_SUPRA); assert_delegation(validator_address, pool_address, 15100000001, 0, 14999999999); stake::assert_stake_pool(pool_address, 15100000001, 0, 0, 14999999999); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, - 14999999999); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, false, 14999999999 + ); - assert!(stake::get_remaining_lockup_secs(pool_address) == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, - 0); + assert!( + stake::get_remaining_lockup_secs(pool_address) + == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, + 0 + ); end_aptos_epoch(); // additionally forwards EPOCH_DURATION seconds // pending_inactive stake should have not been inactivated // 15100000001 * 1.01 active stake + 14999999999 pending_inactive * 1.01 stake assert_delegation(validator_address, pool_address, 15251000001, 0, 15149999998); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, - 15149999998); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, false, 15149999998 + ); stake::assert_stake_pool(pool_address, 15251000001, 0, 0, 15149999998); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS - 3 * EPOCH_DURATION); @@ -2818,8 +3327,9 @@ module supra_framework::pbo_delegation_pool { // 15251000001 * 1.01 active stake + 15149999998 * 1.01 pending_inactive(now inactive) stake assert_delegation(validator_address, pool_address, 15403510001, 15301499997, 0); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, - 15301499997); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, true, 15301499997 + ); stake::assert_stake_pool(pool_address, 15403510001, 15301499997, 0, 0); // add 50 coins from another account @@ -2832,7 +3342,9 @@ module supra_framework::pbo_delegation_pool { fee = get_add_stake_fee(pool_address, 50 * ONE_SUPRA); assert_delegation(delegator_address, pool_address, 4999999999 - fee, 0, 0); assert_delegation(validator_address, pool_address, 15403510001, 15301499997, 0); - stake::assert_stake_pool(pool_address, 15403510001, 15301499997, 50 * ONE_SUPRA, 0); + stake::assert_stake_pool( + pool_address, 15403510001, 15301499997, 50 * ONE_SUPRA, 0 + ); // cannot withdraw stake unlocked by others withdraw(delegator, pool_address, 50 * ONE_SUPRA); @@ -2850,8 +3362,9 @@ module supra_framework::pbo_delegation_pool { // new pending withdrawal can be created on lockup cycle 1 unlock(validator, pool_address, 5403510001); assert_delegation(validator_address, pool_address, 10000000000, 0, 5403510000); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 5403510000); + assert_pending_withdrawal( + validator_address, pool_address, true, 1, false, 5403510000 + ); // end lockup cycle 1 timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -2859,8 +3372,9 @@ module supra_framework::pbo_delegation_pool { // 10000000000 * 1.01 active stake + 5403510000 * 1.01 pending_inactive(now inactive) stake assert_delegation(validator_address, pool_address, 10100000000, 5457545100, 0); - assert_pending_withdrawal(validator_address, pool_address, true, 1, true, - 5457545100); + assert_pending_withdrawal( + validator_address, pool_address, true, 1, true, 5457545100 + ); // unlock when the pending withdrawal exists and gets automatically executed let balance = coin::balance(validator_address); @@ -2868,8 +3382,9 @@ module supra_framework::pbo_delegation_pool { assert!(coin::balance(validator_address) == balance + 5457545100, 0); assert_delegation(validator_address, pool_address, 0, 0, 10100000000); // this is the new pending withdrawal replacing the executed one - assert_pending_withdrawal(validator_address, pool_address, true, 2, false, - 10100000000); + assert_pending_withdrawal( + validator_address, pool_address, true, 2, false, 10100000000 + ); // create dummy validator to ensure the existing validator can leave the set let delegator_address_vec = vector[@0x010]; @@ -2877,9 +3392,10 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(100 * ONE_SUPRA); // lockup time updated as you see above we `fast_forward_seconds` alog with `end_aptos_epoch` - principle_lockup_time = LOCKUP_CYCLE_SECONDS + (LOCKUP_CYCLE_SECONDS - (3 * EPOCH_DURATION)) - + (5 * EPOCH_DURATION); - initialize_test_validator(delegator, + principle_lockup_time = LOCKUP_CYCLE_SECONDS + + (LOCKUP_CYCLE_SECONDS - (3 * EPOCH_DURATION)) + (5 * EPOCH_DURATION); + initialize_test_validator( + delegator, 100 * ONE_SUPRA, true, true, @@ -2891,7 +3407,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); // inactivate validator stake::leave_validator_set(validator, pool_address); end_aptos_epoch(); @@ -2910,8 +3427,9 @@ module supra_framework::pbo_delegation_pool { // 10100000000 * 1.01 * 1.01 pending_inactive stake assert_delegation(validator_address, pool_address, 0, 0, 10303010000); // the pending withdrawal should be reported as still pending - assert_pending_withdrawal(validator_address, pool_address, true, 2, false, - 10303010000); + assert_pending_withdrawal( + validator_address, pool_address, true, 2, false, 10303010000 + ); // validator is inactive and lockup expired => pending_inactive stake is withdrawable balance = coin::balance(validator_address); @@ -2922,8 +3440,9 @@ module supra_framework::pbo_delegation_pool { assert_pending_withdrawal(validator_address, pool_address, false, 0, false, 0); stake::assert_stake_pool(pool_address, 5100500001, 0, 0, 0); // pending_inactive shares pool has not been deleted (as can still `unlock` this OLC) - assert_inactive_shares_pool(pool_address, observed_lockup_cycle(pool_address), true, - 0); + assert_inactive_shares_pool( + pool_address, observed_lockup_cycle(pool_address), true, 0 + ); stake::mint(validator, 30 * ONE_SUPRA); add_stake(validator, pool_address, 30 * ONE_SUPRA); @@ -2931,32 +3450,42 @@ module supra_framework::pbo_delegation_pool { assert_delegation(validator_address, pool_address, 2000000000, 0, 999999999); // the pending withdrawal should be reported as still pending - assert_pending_withdrawal(validator_address, pool_address, true, 2, false, - 999999999); + assert_pending_withdrawal( + validator_address, pool_address, true, 2, false, 999999999 + ); balance = coin::balance(validator_address); // pending_inactive balance would be under threshold => redeem entire balance withdraw(validator, pool_address, 1); // pending_inactive balance has been withdrawn and the pending withdrawal executed assert_delegation(validator_address, pool_address, 2000000000, 0, 999999998); - assert_pending_withdrawal(validator_address, pool_address, true, 2, false, - 999999998); + assert_pending_withdrawal( + validator_address, pool_address, true, 2, false, 999999998 + ); assert!(coin::balance(validator_address) == balance + 1, 0); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_total_coins_inactive( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010, @0x020]; let principle_stake = vector[0, 0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 200 * ONE_SUPRA, true, true, @@ -2968,7 +3497,8 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60); + 60 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3025,13 +3555,18 @@ module supra_framework::pbo_delegation_pool { assert!(total_coins_inactive(pool_address) == inactive, 0); synchronize_delegation_pool(pool_address); // total_coins_inactive == previous inactive stake + previous pending_inactive stake and its rewards - assert!(total_coins_inactive(pool_address) == inactive + pending_inactive + pending_inactive - / 100, 0); + assert!( + total_coins_inactive(pool_address) + == inactive + pending_inactive + pending_inactive / 100, + 0 + ); // withdraw some of inactive stake of delegator 2 let total_coins_inactive = total_coins_inactive(pool_address); withdraw(delegator2, pool_address, 3049999998); - assert!(total_coins_inactive(pool_address) == total_coins_inactive - 3049999997, 0); + assert!( + total_coins_inactive(pool_address) == total_coins_inactive - 3049999997, 0 + ); // unlock some stake from delegator `validator` unlock(validator, pool_address, 50 * ONE_SUPRA); @@ -3041,7 +3576,8 @@ module supra_framework::pbo_delegation_pool { let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); principle_lockup_time = (2 * LOCKUP_CYCLE_SECONDS) + (4 * EPOCH_DURATION); - initialize_test_validator(delegator1, + initialize_test_validator( + delegator1, 100 * ONE_SUPRA, true, true, @@ -3053,7 +3589,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); // inactivate validator stake::leave_validator_set(validator, pool_address); end_aptos_epoch(); @@ -3087,13 +3624,16 @@ module supra_framework::pbo_delegation_pool { } #[test(supra_framework = @supra_framework, validator = @0x123)] - public entry fun test_reactivate_stake_single(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_reactivate_stake_single( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[]; let principle_stake = vector[]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 200 * ONE_SUPRA, true, true, @@ -3105,24 +3645,41 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); // unlock some stake from the active one unlock(validator, pool_address, 100 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 100 * ONE_SUPRA, 0, 100 * ONE_SUPRA); + assert_delegation( + validator_address, + pool_address, + 100 * ONE_SUPRA, + 0, + 100 * ONE_SUPRA + ); stake::assert_stake_pool(pool_address, 100 * ONE_SUPRA, 0, 0, 100 * ONE_SUPRA); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, 100 * ONE_SUPRA); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, false, 100 * ONE_SUPRA + ); // add some stake to pending_active state stake::mint(validator, 150 * ONE_SUPRA); add_stake(validator, pool_address, 150 * ONE_SUPRA); let fee = get_add_stake_fee(pool_address, 150 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 250 * ONE_SUPRA - fee, 0, 100 * ONE_SUPRA); - stake::assert_stake_pool(pool_address, 100 * ONE_SUPRA, 0, 150 * ONE_SUPRA, 100 * ONE_SUPRA); + assert_delegation( + validator_address, + pool_address, + 250 * ONE_SUPRA - fee, + 0, + 100 * ONE_SUPRA + ); + stake::assert_stake_pool( + pool_address, 100 * ONE_SUPRA, 0, 150 * ONE_SUPRA, 100 * ONE_SUPRA + ); // can reactivate only pending_inactive stake reactivate_stake(validator, pool_address, 150 * ONE_SUPRA); @@ -3146,8 +3703,9 @@ module supra_framework::pbo_delegation_pool { // 20200000001 active stake * 1.01 + 14999999999 pending_inactive stake * 1.01 assert_delegation(validator_address, pool_address, 20402000001, 15149999998, 0); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, - 15149999998); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, true, 15149999998 + ); // cannot reactivate inactive stake reactivate_stake(validator, pool_address, 15149999998); @@ -3157,13 +3715,15 @@ module supra_framework::pbo_delegation_pool { unlock(validator, pool_address, 100 * ONE_SUPRA); assert!(coin::balance(validator_address) == 15149999998, 0); assert_delegation(validator_address, pool_address, 10402000002, 0, 9999999999); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 9999999999); + assert_pending_withdrawal( + validator_address, pool_address, true, 1, false, 9999999999 + ); // reactivate the new pending withdrawal almost entirely reactivate_stake(validator, pool_address, 8999999999); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 1000000000); + assert_pending_withdrawal( + validator_address, pool_address, true, 1, false, 1000000000 + ); // reactivate remaining stake of the new pending withdrawal reactivate_stake(validator, pool_address, 1000000000); assert_pending_withdrawal(validator_address, pool_address, false, 0, false, 0); @@ -3171,14 +3731,17 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_withdraw_many( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -3190,7 +3753,8 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60); + 60 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3202,15 +3766,18 @@ module supra_framework::pbo_delegation_pool { add_stake(delegator, pool_address, 200 * ONE_SUPRA); unlock(validator, pool_address, 100 * ONE_SUPRA); - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, 100 * ONE_SUPRA); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, false, 100 * ONE_SUPRA + ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); assert_delegation(delegator_address, pool_address, 200 * ONE_SUPRA, 0, 0); assert_delegation(validator_address, pool_address, 90899999999, 10100000000, 0); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, - 10100000000); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, true, 10100000000 + ); assert_inactive_shares_pool(pool_address, 0, true, 100 * ONE_SUPRA); // check cannot withdraw inactive stake unlocked by others @@ -3221,8 +3788,9 @@ module supra_framework::pbo_delegation_pool { unlock(delegator, pool_address, 100 * ONE_SUPRA); assert_delegation(delegator_address, pool_address, 10000000000, 0, 9999999999); assert_delegation(validator_address, pool_address, 90900000000, 10100000000, 0); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 9999999999); + assert_pending_withdrawal( + delegator_address, pool_address, true, 1, false, 9999999999 + ); // check cannot withdraw inactive stake unlocked by others even if owning pending_inactive withdraw(delegator, pool_address, MAX_U64); @@ -3240,8 +3808,9 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); assert_delegation(delegator_address, pool_address, 10100000000, 10099999998, 0); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, true, - 10099999998); + assert_pending_withdrawal( + delegator_address, pool_address, true, 1, true, 10099999998 + ); assert_inactive_shares_pool(pool_address, 1, true, 9999999999); // use too small of an unlock amount to actually transfer shares to the pending_inactive pool @@ -3250,8 +3819,9 @@ module supra_framework::pbo_delegation_pool { unlock_with_min_stake_disabled(delegator, pool_address, 1); stake::assert_stake_pool(pool_address, 101909000001, 10099999998, 0, 0); assert_delegation(delegator_address, pool_address, 10100000000, 10099999998, 0); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, true, - 10099999998); + assert_pending_withdrawal( + delegator_address, pool_address, true, 1, true, 10099999998 + ); // implicitly execute the pending withdrawal by unlocking min stake to buy 1 share unlock_with_min_stake_disabled(delegator, pool_address, 2); @@ -3265,14 +3835,17 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_inactivate_no_excess_stake( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address_vec = vector[@0x010]; let principle_stake = vector[0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1200 * ONE_SUPRA, true, true, @@ -3284,7 +3857,8 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60); + 60 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3313,7 +3887,8 @@ module supra_framework::pbo_delegation_pool { let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); principle_lockup_time = LOCKUP_CYCLE_SECONDS + (2 * EPOCH_DURATION); - initialize_test_validator(delegator, + initialize_test_validator( + delegator, 100 * ONE_SUPRA, true, true, @@ -3325,7 +3900,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); // inactivate validator stake::leave_validator_set(validator, pool_address); end_aptos_epoch(); @@ -3365,16 +3941,19 @@ module supra_framework::pbo_delegation_pool { assert_delegation(delegator_address, pool_address, 0, 0, 10000000002); assert_delegation(validator_address, pool_address, 103030100001, 20000000001, 0); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, - 20000000001); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 10000000002); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, true, 20000000001 + ); + assert_pending_withdrawal( + delegator_address, pool_address, true, 1, false, 10000000002 + ); stake::assert_stake_pool(pool_address, 103030100001, 20000000001, 0, 10000000002); // reactivate validator stake::join_validator_set(validator, pool_address); - assert!(stake::get_validator_state(pool_address) == VALIDATOR_STATUS_PENDING_ACTIVE, - 0); + assert!( + stake::get_validator_state(pool_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 0 + ); end_aptos_epoch(); assert!(stake::get_validator_state(pool_address) == VALIDATOR_STATUS_ACTIVE, 0); @@ -3382,16 +3961,19 @@ module supra_framework::pbo_delegation_pool { stake::assert_stake_pool(pool_address, 103030100001, 20000000001, 0, 10000000002); synchronize_delegation_pool(pool_address); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, - 20000000001); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 10000000002); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, true, 20000000001 + ); + assert_pending_withdrawal( + delegator_address, pool_address, true, 1, false, 10000000002 + ); assert!(observed_lockup_cycle(pool_address) == observed_lockup_cycle, 0); // cannot withdraw pending_inactive stake anymore withdraw(delegator, pool_address, 10000000002); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 10000000002); + assert_pending_withdrawal( + delegator_address, pool_address, true, 1, false, 10000000002 + ); // earning rewards is resumed from this epoch on end_aptos_epoch(); @@ -3399,25 +3981,32 @@ module supra_framework::pbo_delegation_pool { // new pending_inactive stake earns rewards but so does the old one unlock(validator, pool_address, 104060401001); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 104060401000); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 10100000002); + assert_pending_withdrawal( + validator_address, pool_address, true, 1, false, 104060401000 + ); + assert_pending_withdrawal( + delegator_address, pool_address, true, 1, false, 10100000002 + ); end_aptos_epoch(); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 105101005010); - assert_pending_withdrawal(delegator_address, pool_address, true, 1, false, - 10201000002); + assert_pending_withdrawal( + validator_address, pool_address, true, 1, false, 105101005010 + ); + assert_pending_withdrawal( + delegator_address, pool_address, true, 1, false, 10201000002 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] - public entry fun test_active_stake_rewards(supra_framework: &signer, validator: &signer,) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { + public entry fun test_active_stake_rewards( + supra_framework: &signer, validator: &signer + ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[]; let principle_stake = vector[]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -3429,7 +4018,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3484,8 +4074,13 @@ module supra_framework::pbo_delegation_pool { add_stake(validator, pool_address, 1000 * ONE_SUPRA); fee = get_add_stake_fee(pool_address, 1000 * ONE_SUPRA); - assert_delegation(validator_address, pool_address, 211717346653 - fee, 20199999998, - 0); + assert_delegation( + validator_address, + pool_address, + 211717346653 - fee, + 20199999998, + 0 + ); end_aptos_epoch(); // 111717346653 active stake * 1.01 + 100000000000 pending_active stake + 20199999998 inactive stake @@ -3498,14 +4093,17 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_active_stake_rewards_multiple( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[0]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 200 * ONE_SUPRA, true, true, @@ -3517,7 +4115,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3572,14 +4171,15 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_pending_inactive_stake_rewards( - supra_framework: &signer, validator: &signer, + supra_framework: &signer, validator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[]; let principle_stake = vector[]; let coin = stake::mint_coins(0); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -3591,7 +4191,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3630,19 +4231,27 @@ module supra_framework::pbo_delegation_pool { assert_delegation(validator_address, pool_address, 68926429037, 21020200996, 0); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_out_of_order_redeem( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -3654,7 +4263,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -3675,8 +4285,9 @@ module supra_framework::pbo_delegation_pool { // create the pending withdrawal of delegator 1 in lockup cycle 0 unlock(delegator1, pool_address, 150 * ONE_SUPRA); - assert_pending_withdrawal(delegator1_address, pool_address, true, 0, false, - 14999999999); + assert_pending_withdrawal( + delegator1_address, pool_address, true, 0, false, 14999999999 + ); // move to lockup cycle 1 timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); @@ -3684,27 +4295,32 @@ module supra_framework::pbo_delegation_pool { // create the pending withdrawal of delegator 2 in lockup cycle 1 unlock(delegator2, pool_address, 150 * ONE_SUPRA); - assert_pending_withdrawal(delegator2_address, pool_address, true, 1, false, - 14999999999); + assert_pending_withdrawal( + delegator2_address, pool_address, true, 1, false, 14999999999 + ); // 14999999999 pending_inactive stake * 1.01 - assert_pending_withdrawal(delegator1_address, pool_address, true, 0, true, - 15149999998); + assert_pending_withdrawal( + delegator1_address, pool_address, true, 0, true, 15149999998 + ); // move to lockup cycle 2 timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - assert_pending_withdrawal(delegator2_address, pool_address, true, 1, true, - 15149999998); - assert_pending_withdrawal(delegator1_address, pool_address, true, 0, true, - 15149999998); + assert_pending_withdrawal( + delegator2_address, pool_address, true, 1, true, 15149999998 + ); + assert_pending_withdrawal( + delegator1_address, pool_address, true, 0, true, 15149999998 + ); // both delegators who unlocked at different lockup cycles should be able to withdraw their stakes withdraw(delegator1, pool_address, 15149999998); withdraw(delegator2, pool_address, 5149999998); - assert_pending_withdrawal(delegator2_address, pool_address, true, 1, true, - 10000000001); + assert_pending_withdrawal( + delegator2_address, pool_address, true, 1, true, 10000000001 + ); assert_pending_withdrawal(delegator1_address, pool_address, false, 0, false, 0); assert!(coin::balance(delegator1_address) == 15149999998, 0); assert!(coin::balance(delegator2_address) == 5149999997, 0); @@ -3716,11 +4332,13 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - assert_pending_withdrawal(delegator2_address, pool_address, true, 1, true, - 10000000001); + assert_pending_withdrawal( + delegator2_address, pool_address, true, 1, true, 10000000001 + ); // 9999999999 pending_inactive stake * 1.01 - assert_pending_withdrawal(delegator1_address, pool_address, true, 2, true, - 10099999998); + assert_pending_withdrawal( + delegator1_address, pool_address, true, 2, true, 10099999998 + ); // withdraw inactive stake of delegator 2 left from lockup cycle 1 in cycle 3 withdraw(delegator2, pool_address, 10000000001); @@ -3729,17 +4347,26 @@ module supra_framework::pbo_delegation_pool { // withdraw inactive stake of delegator 1 left from previous lockup cycle withdraw(delegator1, pool_address, 10099999998); - assert!(coin::balance(delegator1_address) == 15149999998 + 10099999998, - 0); + assert!( + coin::balance(delegator1_address) == 15149999998 + 10099999998, + 0 + ); assert_pending_withdrawal(delegator1_address, pool_address, false, 0, false, 0); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_operator_fee( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let validator_address = signer::address_of(validator); @@ -3750,7 +4377,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; // create delegation pool of commission fee 12.65% - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::none(), 1265, vector::empty(), @@ -3760,7 +4388,8 @@ module supra_framework::pbo_delegation_pool { vector[1], 1, principle_lockup_time, - 60); + 60 + ); let pool_address = get_owned_pool_address(validator_address); assert!(stake::get_operator(pool_address) == validator_address, 0); @@ -3832,8 +4461,9 @@ module supra_framework::pbo_delegation_pool { // distribute operator pending_inactive commission rewards synchronize_delegation_pool(pool_address); // 99999999 pending_inactive rewards * 0.1265 - assert_pending_withdrawal(validator_address, pool_address, true, 0, false, - 12649998); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, false, 12649998 + ); // 209090300 active rewards * 0.1265 + 115658596 active stake * 1.008735 // 99999999 pending_inactive rewards * 0.1265 @@ -3854,7 +4484,9 @@ module supra_framework::pbo_delegation_pool { assert_delegation(validator_address, pool_address, 171083360, 25536995, 0); // distribute operator pending_inactive commission rewards synchronize_delegation_pool(pool_address); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, 25536995); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, true, 25536995 + ); // check operator is not rewarded by `add_stake` fees stake::mint(delegator1, 100 * ONE_SUPRA); @@ -3878,7 +4510,9 @@ module supra_framework::pbo_delegation_pool { // in-flight pending_inactive commission can coexist with previous inactive commission assert_delegation(validator_address, pool_address, 228553872, 25536996, 12649999); - assert_pending_withdrawal(validator_address, pool_address, true, 0, true, 25536996); + assert_pending_withdrawal( + validator_address, pool_address, true, 0, true, 25536996 + ); // distribute in-flight pending_inactive commission, implicitly executing the inactive withdrawal of operator coin::register(validator); @@ -3888,16 +4522,24 @@ module supra_framework::pbo_delegation_pool { // in-flight commission has been synced, implicitly used to buy shares for operator // expect operator stake to be slightly less than previously reported by `Self::get_stake` assert_delegation(validator_address, pool_address, 228553872, 0, 12649998); - assert_pending_withdrawal(validator_address, pool_address, true, 1, false, - 12649998); + assert_pending_withdrawal( + validator_address, pool_address, true, 1, false, 12649998 + ); } - #[test(supra_framework = @supra_framework, old_operator = @0x123, delegator = @0x010, new_operator = @0x020)] + #[ + test( + supra_framework = @supra_framework, + old_operator = @0x123, + delegator = @0x010, + new_operator = @0x020 + ) + ] public entry fun test_change_operator( supra_framework: &signer, old_operator: &signer, delegator: &signer, - new_operator: &signer, + new_operator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); @@ -3912,7 +4554,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; // create delegation pool of commission fee 12.65% - initialize_delegation_pool(old_operator, + initialize_delegation_pool( + old_operator, option::none(), 1265, vector::empty(), @@ -3922,7 +4565,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(old_operator_address); assert!(stake::get_operator(pool_address) == old_operator_address, 0); @@ -3968,13 +4612,21 @@ module supra_framework::pbo_delegation_pool { assert_delegation(new_operator_address, pool_address, 26050290, 0, 26050290); } - #[test(supra_framework = @supra_framework, operator1 = @0x123, delegator = @0x010, beneficiary = @0x020, operator2 = @0x030)] + #[ + test( + supra_framework = @supra_framework, + operator1 = @0x123, + delegator = @0x010, + beneficiary = @0x020, + operator2 = @0x030 + ) + ] public entry fun test_set_beneficiary_for_operator( supra_framework: &signer, operator1: &signer, delegator: &signer, beneficiary: &signer, - operator2: &signer, + operator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); @@ -3991,7 +4643,8 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(0); let principle_lockup_time = 0; // create delegation pool of commission fee 12.65% - initialize_delegation_pool(operator1, + initialize_delegation_pool( + operator1, option::none(), 1265, vector::empty(), @@ -4001,7 +4654,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(operator1_address); assert!(stake::get_operator(pool_address) == operator1_address, 0); assert!(beneficiary_for_operator(operator1_address) == operator1_address, 0); @@ -4056,7 +4710,9 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, operator = @0x123, delegator = @0x010)] public entry fun test_update_commission_percentage( - supra_framework: &signer, operator: &signer, delegator: &signer, + supra_framework: &signer, + operator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); @@ -4067,7 +4723,8 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(0); let principle_lockup_time = 0; // create delegation pool of commission fee 12.65% - initialize_delegation_pool(operator, + initialize_delegation_pool( + operator, option::none(), 1265, vector::empty(), @@ -4077,7 +4734,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(operator_address); assert!(stake::get_operator(pool_address) == operator_address, 0); @@ -4129,7 +4787,9 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, operator = @0x123, delegator = @0x010)] #[expected_failure(abort_code = 196629, location = Self)] public entry fun test_last_minute_commission_rate_change_failed( - supra_framework: &signer, operator: &signer, delegator: &signer, + supra_framework: &signer, + operator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let operator_address = signer::address_of(operator); @@ -4139,7 +4799,8 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; // create delegation pool of commission fee 12.65% - initialize_delegation_pool(operator, + initialize_delegation_pool( + operator, option::none(), 1265, vector::empty(), @@ -4149,7 +4810,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let pool_address = get_owned_pool_address(operator_address); assert!(stake::get_operator(pool_address) == operator_address, 0); @@ -4189,19 +4851,27 @@ module supra_framework::pbo_delegation_pool { update_commission_percentage(operator, 2255); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_min_stake_is_preserved( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x111]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 100 * ONE_SUPRA, true, false, @@ -4213,7 +4883,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -4259,8 +4930,11 @@ module supra_framework::pbo_delegation_pool { assert_delegation(delegator1_address, pool_address, 100000000, 0, 4900000000); // pending_inactive balance would be under threshold => move entire balance - reactivate_stake(delegator1, pool_address, 4000000000 - (MIN_COINS_ON_SHARES_POOL - - 1)); + reactivate_stake( + delegator1, + pool_address, + 4000000000 - (MIN_COINS_ON_SHARES_POOL - 1) + ); assert_delegation(delegator1_address, pool_address, 4000000001, 0, 999999999); // active + pending_inactive balance < 2 * MIN_COINS_ON_SHARES_POOL @@ -4315,8 +4989,11 @@ module supra_framework::pbo_delegation_pool { #[test(staker = @0xe256f4f4e2986cada739e339895cf5585082ff247464cab8ec56eea726bd2263)] public entry fun test_get_expected_stake_pool_address(staker: address) { let pool_address = get_expected_stake_pool_address(staker, vector[0x42, 0x42]); - assert!(pool_address == @ - 0xcb5678be9ec64067c2c3f9f8de78e19509411b053d723d2788ebf1f7ba02f04b, 0); + assert!( + pool_address + == @0xcb5678be9ec64067c2c3f9f8de78e19509411b053d723d2788ebf1f7ba02f04b, + 0 + ); } #[test_only] @@ -4325,14 +5002,15 @@ module supra_framework::pbo_delegation_pool { pool_address: address, active_stake: u64, inactive_stake: u64, - pending_inactive_stake: u64, + pending_inactive_stake: u64 ) acquires DelegationPool, BeneficiaryForOperator { - let (actual_active, actual_inactive, actual_pending_inactive) = get_stake( - pool_address, delegator_address - ); + let (actual_active, actual_inactive, actual_pending_inactive) = + get_stake(pool_address, delegator_address); assert!(actual_active == active_stake, actual_active); assert!(actual_inactive == inactive_stake, actual_inactive); - assert!(actual_pending_inactive == pending_inactive_stake, actual_pending_inactive); + assert!( + actual_pending_inactive == pending_inactive_stake, actual_pending_inactive + ); } #[test_only] @@ -4342,28 +5020,30 @@ module supra_framework::pbo_delegation_pool { exists: bool, olc: u64, inactive: bool, - stake: u64, + stake: u64 ) acquires DelegationPool { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); - let (withdrawal_exists, withdrawal_olc) = pending_withdrawal_exists(pool, - delegator_address); + let (withdrawal_exists, withdrawal_olc) = + pending_withdrawal_exists(pool, delegator_address); assert!(withdrawal_exists == exists, 0); assert!(withdrawal_olc.index == olc, withdrawal_olc.index); - let (withdrawal_inactive, withdrawal_stake) = get_pending_withdrawal(pool_address, - delegator_address); + let (withdrawal_inactive, withdrawal_stake) = + get_pending_withdrawal(pool_address, delegator_address); assert!(withdrawal_inactive == inactive, 0); assert!(withdrawal_stake == stake, withdrawal_stake); } #[test_only] - public fun assert_inactive_shares_pool(pool_address: address, olc: u64, exists: bool, stake: u64,) acquires DelegationPool { + public fun assert_inactive_shares_pool( + pool_address: address, olc: u64, exists: bool, stake: u64 + ) acquires DelegationPool { assert_delegation_pool_exists(pool_address); let pool = borrow_global(pool_address); assert!(table::contains(&pool.inactive_shares, olc_with_index(olc)) == exists, 0); if (exists) { - let actual_stake = total_coins(table::borrow(&pool.inactive_shares, - olc_with_index(olc))); + let actual_stake = + total_coins(table::borrow(&pool.inactive_shares, olc_with_index(olc))); assert!(actual_stake == stake, actual_stake); } else { assert!(0 == stake, 0); @@ -4378,14 +5058,17 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] #[expected_failure(abort_code = 65561, location = Self)] public entry fun test_withdraw_before_principle_lockup_time_fail( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 1000000; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -4397,7 +5080,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -4409,14 +5093,17 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] public entry fun test_withdraw_after_principle_lockup_time( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; let principle_stake = vector[100 * ONE_SUPRA]; let coin = stake::mint_coins(100 * ONE_SUPRA); let principle_lockup_time = 1000000; - initialize_test_validator(validator, + initialize_test_validator( + validator, 1000 * ONE_SUPRA, true, true, @@ -4428,7 +5115,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); @@ -4437,19 +5125,27 @@ module supra_framework::pbo_delegation_pool { unlock(delegator, pool_address, 100 * ONE_SUPRA); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_unlock_mutiple_delegators( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010, @0x020]; let principle_stake = vector[100 * ONE_SUPRA, 200 * ONE_SUPRA]; let coin = stake::mint_coins(300 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4461,7 +5157,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); unlock(delegator1, pool_address, 11 * ONE_SUPRA); @@ -4470,7 +5167,9 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010)] public entry fun test_unlock_mutiple_times( - supra_framework: &signer, validator: &signer, delegator1: &signer, + supra_framework: &signer, + validator: &signer, + delegator1: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010, @0x020]; @@ -4479,7 +5178,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 1000000; let delegator1_address = signer::address_of(delegator1); supra_account::create_account(delegator1_address); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4491,7 +5191,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); stake::mint(delegator1, 1000 * ONE_SUPRA); @@ -4501,13 +5202,20 @@ module supra_framework::pbo_delegation_pool { unlock(delegator1, pool_address, 600 * ONE_SUPRA); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] #[expected_failure(abort_code = 65561, location = Self)] public entry fun test_multiple_users( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010]; @@ -4518,7 +5226,8 @@ module supra_framework::pbo_delegation_pool { let delegator2_address = signer::address_of(delegator2); supra_account::create_account(delegator1_address); supra_account::create_account(delegator2_address); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4530,7 +5239,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); stake::mint(delegator1, 1000 * ONE_SUPRA); @@ -4548,12 +5258,15 @@ module supra_framework::pbo_delegation_pool { } #[test_only] - fun generate_multisig_account(owner: &signer, addition_owner: vector
, threshold: u64) - : address { + fun generate_multisig_account( + owner: &signer, addition_owner: vector
, threshold: u64 + ): address { let owner_addr = aptos_std::signer::address_of(owner); - let multisig_addr = multisig_account::get_next_multisig_account_address(owner_addr); - multisig_account::create_with_owners(owner, addition_owner, threshold, vector[], - vector[], 300); + let multisig_addr = + multisig_account::get_next_multisig_account_address(owner_addr); + multisig_account::create_with_owners( + owner, addition_owner, threshold, vector[], vector[], 300 + ); multisig_addr } @@ -4571,7 +5284,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4583,11 +5297,16 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); - replace_delegator(&account::create_signer_for_test(multisig), pool_address, @0x010, @ - 0x0101); + replace_delegator( + &account::create_signer_for_test(multisig), + pool_address, + @0x010, + @0x0101 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] @@ -4603,7 +5322,8 @@ module supra_framework::pbo_delegation_pool { let coin = stake::mint_coins(300 * ONE_SUPRA); let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[], 1); - initialize_delegation_pool(validator, + initialize_delegation_pool( + validator, option::some(multisig), 0, vector::empty(), @@ -4613,7 +5333,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] @@ -4630,7 +5351,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4642,7 +5364,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let new_multisig = generate_multisig_account(supra_framework, vector[@0x12234], 2); let multisig_signer = account::create_signer_for_test(new_multisig); @@ -4652,19 +5375,27 @@ module supra_framework::pbo_delegation_pool { replace_delegator(&multisig_signer, pool_address, @0x010, @0x0101); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_lose_shares_small( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010, @0x020]; let principle_stake = vector[ONE_SUPRA, 1000 * ONE_SUPRA]; let coin = stake::mint_coins(1001 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 100 * ONE_SUPRA, true, true, @@ -4676,19 +5407,22 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); stake::mint(validator, 150 * ONE_SUPRA); add_stake(validator, pool_address, 150 * ONE_SUPRA); let one_year_in_secs = 31536000; let reward_period_start_time_in_sec = timestamp::now_seconds(); - staking_config::initialize_rewards(supra_framework, + staking_config::initialize_rewards( + supra_framework, fixed_point64::create_from_rational(1, 100), fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100),); + fixed_point64::create_from_rational(0, 100) + ); let index = 0; while (index < 1828) { end_aptos_epoch(); @@ -4699,30 +5433,47 @@ module supra_framework::pbo_delegation_pool { assert_delegation(delegator1_address, pool_address, 7933617798152065, 0, 0); stake::assert_stake_pool(pool_address, 9913173264836398460, 0, 0, 0); unlock(delegator1, pool_address, 1 * ONE_SUPRA); - assert_delegation(delegator1_address, pool_address, 7933617698152064, 0, 100000000); + assert_delegation( + delegator1_address, pool_address, 7933617698152064, 0, 100000000 + ); stake::assert_stake_pool(pool_address, 9913173264736398460, 0, 0, 100000000); unlock(delegator1, pool_address, 1 * ONE_SUPRA); stake::assert_stake_pool(pool_address, 9913173264636398461, 0, 0, 199999999); - assert_delegation(delegator1_address, pool_address, 7933617598152064, 0, 199999999); + assert_delegation( + delegator1_address, pool_address, 7933617598152064, 0, 199999999 + ); assert_delegation(delegator2_address, pool_address, 7933617798152065133, 0, 0); unlock(delegator2, pool_address, 1000 * ONE_SUPRA); - assert_delegation(delegator2_address, pool_address, 7933617698152065134, 0, - 99999999999); + assert_delegation( + delegator2_address, + pool_address, + 7933617698152065134, + 0, + 99999999999 + ); } - #[test(supra_framework = @supra_framework, validator = @0x123, delegator1 = @0x010, delegator2 = @0x020)] + #[ + test( + supra_framework = @supra_framework, + validator = @0x123, + delegator1 = @0x010, + delegator2 = @0x020 + ) + ] public entry fun test_lose_shares_large( supra_framework: &signer, validator: &signer, delegator1: &signer, - delegator2: &signer, + delegator2: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); let delegator_address = vector[@0x010, @0x020]; let principle_stake = vector[ONE_SUPRA, 90000000000 * ONE_SUPRA]; let coin = stake::mint_coins(90000000001 * ONE_SUPRA); let principle_lockup_time = 0; - initialize_test_validator(validator, + initialize_test_validator( + validator, 100 * ONE_SUPRA, true, true, @@ -4734,19 +5485,22 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); stake::mint(validator, 150 * ONE_SUPRA); add_stake(validator, pool_address, 150 * ONE_SUPRA); let one_year_in_secs = 31536000; let reward_period_start_time_in_sec = timestamp::now_seconds(); - staking_config::initialize_rewards(supra_framework, + staking_config::initialize_rewards( + supra_framework, fixed_point64::create_from_rational(1, 100), fixed_point64::create_from_rational(1, 100), one_year_in_secs, reward_period_start_time_in_sec, - fixed_point64::create_from_rational(0, 100),); + fixed_point64::create_from_rational(0, 100) + ); let index = 0; while (index < 10) { end_aptos_epoch(); @@ -4763,8 +5517,13 @@ module supra_framework::pbo_delegation_pool { assert_delegation(delegator1_address, pool_address, 0, 0, 110462212); assert_delegation(delegator2_address, pool_address, 9941599128700840588, 0, 0); unlock(delegator2, pool_address, 1 * ONE_SUPRA); - assert_delegation(delegator2_address, pool_address, 9941599128600840588, 0, - 100000000); + assert_delegation( + delegator2_address, + pool_address, + 9941599128600840588, + 0, + 100000000 + ); } #[test(supra_framework = @supra_framework, validator = @0x123)] @@ -4781,7 +5540,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4793,7 +5553,8 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let multisig_signer = account::create_signer_for_test(multisig); let validator_address = signer::address_of(validator); @@ -4808,7 +5569,9 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] /// if old_delegator has already unlocked 100, the new_delegator should be able to withdraw 100 coins public entry fun test_replace_delegation_before_withdraw_and_after_withdraw_success( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); account::create_account_for_test(signer::address_of(validator)); @@ -4819,7 +5582,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4831,32 +5595,50 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); unlock(delegator, pool_address, 100 * ONE_SUPRA); - assert_delegation(delegator_address, pool_address, 200 * ONE_SUPRA, 0, 100 * ONE_SUPRA); + assert_delegation( + delegator_address, + pool_address, + 200 * ONE_SUPRA, + 0, + 100 * ONE_SUPRA + ); let multisig_signer = account::create_signer_for_test(multisig); let new_delegator_address = @0x0101; - replace_delegator(&multisig_signer, pool_address, delegator_address, - new_delegator_address); + replace_delegator( + &multisig_signer, + pool_address, + delegator_address, + new_delegator_address + ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - withdraw(&account::create_signer_for_test(new_delegator_address), pool_address, - 100 * ONE_SUPRA); - assert!(coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, 0); + withdraw( + &account::create_signer_for_test(new_delegator_address), + pool_address, + 100 * ONE_SUPRA + ); + assert!( + coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, 0 + ); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] #[expected_failure(abort_code = 65545, location = Self)] /// after replace_delegator` succeeds, old_delegator must not be able to perform unlock or withdraw or vote (if partial_voting is enable) public entry fun test_replace_delegation_after_withdraw_using_old_address_failure( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); account::create_account_for_test(signer::address_of(validator)); @@ -4867,7 +5649,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4879,15 +5662,20 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let multisig_signer = account::create_signer_for_test(multisig); let new_delegator_address = @0x0101; - replace_delegator(&multisig_signer, pool_address, delegator_address, - new_delegator_address); + replace_delegator( + &multisig_signer, + pool_address, + delegator_address, + new_delegator_address + ); unlock(delegator, pool_address, 100 * ONE_SUPRA); @@ -4900,7 +5688,9 @@ module supra_framework::pbo_delegation_pool { #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] /// after replace_delegator succeeds, new_delegator should be able to perform unlock and withdraw on the funds as per unlocking schedule public entry fun test_replace_delegation_unlock_and_withdraw_success( - supra_framework: &signer, validator: &signer, delegator: &signer, + supra_framework: &signer, + validator: &signer, + delegator: &signer ) acquires DelegationPoolOwnership, DelegationPool, GovernanceRecords, BeneficiaryForOperator, NextCommissionPercentage { initialize_for_test(supra_framework); account::create_account_for_test(signer::address_of(validator)); @@ -4911,7 +5701,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4923,26 +5714,38 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let multisig_signer = account::create_signer_for_test(multisig); let new_delegator_address = @0x0101; - let new_delegator_address_signer = &account::create_signer_for_test( + let new_delegator_address_signer = + &account::create_signer_for_test(new_delegator_address); + replace_delegator( + &multisig_signer, + pool_address, + delegator_address, new_delegator_address ); - replace_delegator(&multisig_signer, pool_address, delegator_address, - new_delegator_address); unlock(new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); - assert_delegation(new_delegator_address, pool_address, 200 * ONE_SUPRA, 0, 100 * ONE_SUPRA); + assert_delegation( + new_delegator_address, + pool_address, + 200 * ONE_SUPRA, + 0, + 100 * ONE_SUPRA + ); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); withdraw(new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); - assert!(coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, 0); + assert!( + coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, 0 + ); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] @@ -4959,7 +5762,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 0; let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -4971,15 +5775,15 @@ module supra_framework::pbo_delegation_pool { vector[2, 2, 3], 10, principle_lockup_time, - 12); + 12 + ); let validator_address = signer::address_of(validator); let pool_address = get_owned_pool_address(validator_address); let new_delegator_address = @0x0215; - let new_delegator_address_signer = account::create_account_for_test( - new_delegator_address - ); + let new_delegator_address_signer = + account::create_account_for_test(new_delegator_address); stake::mint(&new_delegator_address_signer, 100 * ONE_SUPRA); assert!(coin::balance(new_delegator_address) == (100 * ONE_SUPRA), 0); @@ -4987,13 +5791,15 @@ module supra_framework::pbo_delegation_pool { add_stake(&new_delegator_address_signer, pool_address, 100 * ONE_SUPRA); assert!(coin::balance(new_delegator_address) == 0, 0); - unlock(&new_delegator_address_signer, pool_address,(100 * ONE_SUPRA)); + unlock(&new_delegator_address_signer, pool_address, (100 * ONE_SUPRA)); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - withdraw(&new_delegator_address_signer, pool_address,(100 * ONE_SUPRA)); - assert!(coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, 0); + withdraw(&new_delegator_address_signer, pool_address, (100 * ONE_SUPRA)); + assert!( + coin::balance(new_delegator_address) == (100 * ONE_SUPRA) - 1, 0 + ); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] @@ -5012,7 +5818,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5038,8 +5845,10 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 10); } @@ -5060,7 +5869,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5092,56 +5902,71 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (70 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(80 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (80 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(90 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (90 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 16); // after 10 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(100 * ONE_SUPRA) - - 10); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (100 * ONE_SUPRA) - 10 + ); assert!(unlock_coin, 17); // after 11 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address, 100 * ONE_SUPRA); + let unlock_coin = + can_principle_unlock(delegator_address, pool_address, 100 * ONE_SUPRA); assert!(unlock_coin, 18); } @@ -5160,7 +5985,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5206,14 +6032,19 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(100 * ONE_SUPRA)); + let unlock_coin = + can_principle_unlock(delegator_address, pool_address, (100 * ONE_SUPRA)); assert!(unlock_coin, 11); - let unlock_schedule = borrow_global(pool_address).principle_unlock_schedule; + let unlock_schedule = + borrow_global(pool_address).principle_unlock_schedule; let cfraction_upperbound = fixed_point64::create_from_rational(3, 2); - assert!(fixed_point64::less(unlock_schedule.cumulative_unlocked_fraction, - cfraction_upperbound), - unlock_schedule.last_unlock_period); + assert!( + fixed_point64::less( + unlock_schedule.cumulative_unlocked_fraction, cfraction_upperbound + ), + unlock_schedule.last_unlock_period + ); } #[test(supra_framework = @supra_framework, validator = @0x123, delegator = @0x010)] @@ -5230,7 +6061,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5261,8 +6093,10 @@ module supra_framework::pbo_delegation_pool { timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (20 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5280,7 +6114,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5312,15 +6147,19 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (50 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5338,7 +6177,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5370,22 +6210,28 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (60 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5403,7 +6249,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5435,29 +6282,37 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (70 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5475,7 +6330,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5507,36 +6363,46 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (70 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(80 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (80 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5554,7 +6420,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5586,43 +6453,55 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (70 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(80 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (80 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(90 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (90 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5640,7 +6519,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5672,50 +6552,64 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (70 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(80 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (80 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(90 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (90 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 16); // after 10 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(100 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (100 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } @@ -5733,7 +6627,8 @@ module supra_framework::pbo_delegation_pool { let principle_lockup_time = 7776000; // 3 month cliff let multisig = generate_multisig_account(validator, vector[@0x12134], 2); - initialize_test_validator(validator, + initialize_test_validator( + validator, 0, true, true, @@ -5765,57 +6660,73 @@ module supra_framework::pbo_delegation_pool { end_aptos_epoch(); // It's acceptable to round off 9 because this coin will remain locked and won't be transferred anywhere. - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(20 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (20 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 11); // after 5 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(50 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (50 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 12); // after 6 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(60 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (60 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 13); // after 7 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(70 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (70 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 14); // after 8 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(80 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (80 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 15); // after 9 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(90 * ONE_SUPRA) - - 9); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (90 * ONE_SUPRA) - 9 + ); assert!(unlock_coin, 16); // after 10 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(100 * ONE_SUPRA) - - 10); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (100 * ONE_SUPRA) - 10 + ); assert!(unlock_coin, 17); // after 11 months timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS); end_aptos_epoch(); - let unlock_coin = can_principle_unlock(delegator_address, pool_address,(100 * ONE_SUPRA) - + 1); + let unlock_coin = + can_principle_unlock( + delegator_address, pool_address, (100 * ONE_SUPRA) + 1 + ); assert!(unlock_coin, 20); } } diff --git a/aptos-move/framework/supra-framework/sources/primary_fungible_store.move b/aptos-move/framework/supra-framework/sources/primary_fungible_store.move index 13a81a91ee45c..07a805e70bb9d 100644 --- a/aptos-move/framework/supra-framework/sources/primary_fungible_store.move +++ b/aptos-move/framework/supra-framework/sources/primary_fungible_store.move @@ -13,7 +13,15 @@ /// fungible asset to it. This emits an deposit event. module supra_framework::primary_fungible_store { use supra_framework::dispatchable_fungible_asset; - use supra_framework::fungible_asset::{Self, FungibleAsset, FungibleStore, Metadata, MintRef, TransferRef, BurnRef}; + use supra_framework::fungible_asset::{ + Self, + FungibleAsset, + FungibleStore, + Metadata, + MintRef, + TransferRef, + BurnRef + }; use supra_framework::object::{Self, Object, ConstructorRef, DeriveRef}; use std::option::Option; @@ -25,7 +33,7 @@ module supra_framework::primary_fungible_store { /// stores for users with deterministic addresses so that users can easily deposit/withdraw/transfer fungible /// assets. struct DeriveRefPod has key { - metadata_derive_ref: DeriveRef, + metadata_derive_ref: DeriveRef } /// Create a fungible asset with primary store support. When users transfer fungible assets to each other, their @@ -38,7 +46,7 @@ module supra_framework::primary_fungible_store { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ) { fungible_asset::add_fungibility( constructor_ref, @@ -47,18 +55,20 @@ module supra_framework::primary_fungible_store { symbol, decimals, icon_uri, - project_uri, + project_uri ); let metadata_obj = &object::generate_signer(constructor_ref); - move_to(metadata_obj, DeriveRefPod { - metadata_derive_ref: object::generate_derive_ref(constructor_ref), - }); + move_to( + metadata_obj, + DeriveRefPod { + metadata_derive_ref: object::generate_derive_ref(constructor_ref) + } + ); } /// Ensure that the primary store object for the given address exists. If it doesn't, create it. public fun ensure_primary_store_exists( - owner: address, - metadata: Object, + owner: address, metadata: Object ): Object acquires DeriveRefPod { let store_addr = primary_store_address(owner, metadata); if (fungible_asset::store_exists(store_addr)) { @@ -70,8 +80,7 @@ module supra_framework::primary_fungible_store { /// Create a primary store object to hold fungible asset for the given address. public fun create_primary_store( - owner_addr: address, - metadata: Object, + owner_addr: address, metadata: Object ): Object acquires DeriveRefPod { let metadata_addr = object::object_address(&metadata); object::address_to_object(metadata_addr); @@ -86,41 +95,52 @@ module supra_framework::primary_fungible_store { #[view] /// Get the address of the primary store for the given account. - public fun primary_store_address(owner: address, metadata: Object): address { + public fun primary_store_address( + owner: address, metadata: Object + ): address { let metadata_addr = object::object_address(&metadata); object::create_user_derived_object_address(owner, metadata_addr) } #[view] /// Get the primary store object for the given account. - public fun primary_store(owner: address, metadata: Object): Object { + public fun primary_store(owner: address, metadata: Object): + Object { let store = primary_store_address(owner, metadata); object::address_to_object(store) } #[view] /// Return whether the given account's primary store exists. - public fun primary_store_exists(account: address, metadata: Object): bool { + public fun primary_store_exists( + account: address, metadata: Object + ): bool { fungible_asset::store_exists(primary_store_address(account, metadata)) } /// Get the address of the primary store for the given account. /// Use instead of the corresponding view functions for dispatchable hooks to avoid circular dependencies of modules. - public inline fun primary_store_address_inlined(owner: address, metadata: Object): address { + public inline fun primary_store_address_inlined( + owner: address, metadata: Object + ): address { let metadata_addr = object::object_address(&metadata); object::create_user_derived_object_address(owner, metadata_addr) } /// Get the primary store object for the given account. /// Use instead of the corresponding view functions for dispatchable hooks to avoid circular dependencies of modules. - public inline fun primary_store_inlined(owner: address, metadata: Object): Object { + public inline fun primary_store_inlined( + owner: address, metadata: Object + ): Object { let store = primary_store_address_inlined(owner, metadata); object::address_to_object(store) } /// Return whether the given account's primary store exists. /// Use instead of the corresponding view functions for dispatchable hooks to avoid circular dependencies of modules. - public inline fun primary_store_exists_inlined(account: address, metadata: Object): bool { + public inline fun primary_store_exists_inlined( + account: address, metadata: Object + ): bool { fungible_asset::store_exists(primary_store_address_inlined(account, metadata)) } @@ -129,13 +149,13 @@ module supra_framework::primary_fungible_store { public fun balance(account: address, metadata: Object): u64 { if (primary_store_exists(account, metadata)) { fungible_asset::balance(primary_store(account, metadata)) - } else { - 0 - } + } else { 0 } } #[view] - public fun is_balance_at_least(account: address, metadata: Object, amount: u64): bool { + public fun is_balance_at_least( + account: address, metadata: Object, amount: u64 + ): bool { if (primary_store_exists(account, metadata)) { fungible_asset::is_balance_at_least(primary_store(account, metadata), amount) } else { @@ -148,13 +168,13 @@ module supra_framework::primary_fungible_store { public fun is_frozen(account: address, metadata: Object): bool { if (primary_store_exists(account, metadata)) { fungible_asset::is_frozen(primary_store(account, metadata)) - } else { - false - } + } else { false } } /// Withdraw `amount` of fungible asset from the given account's primary store. - public fun withdraw(owner: &signer, metadata: Object, amount: u64): FungibleAsset acquires DeriveRefPod { + public fun withdraw( + owner: &signer, metadata: Object, amount: u64 + ): FungibleAsset acquires DeriveRefPod { let store = ensure_primary_store_exists(signer::address_of(owner), metadata); // Check if the store object has been burnt or not. If so, unburn it first. may_be_unburn(owner, store); @@ -180,13 +200,16 @@ module supra_framework::primary_fungible_store { sender: &signer, metadata: Object, recipient: address, - amount: u64, + amount: u64 ) acquires DeriveRefPod { - let sender_store = ensure_primary_store_exists(signer::address_of(sender), metadata); + let sender_store = + ensure_primary_store_exists(signer::address_of(sender), metadata); // Check if the sender store object has been burnt or not. If so, unburn it first. may_be_unburn(sender, sender_store); let recipient_store = ensure_primary_store_exists(recipient, metadata); - dispatchable_fungible_asset::transfer(sender, sender_store, recipient_store, amount); + dispatchable_fungible_asset::transfer( + sender, sender_store, recipient_store, amount + ); } /// Transfer `amount` of fungible asset from sender's primary store to receiver's primary store. @@ -196,9 +219,10 @@ module supra_framework::primary_fungible_store { metadata: Object, recipient: address, amount: u64, - expected: u64, + expected: u64 ) acquires DeriveRefPod { - let sender_store = ensure_primary_store_exists(signer::address_of(sender), metadata); + let sender_store = + ensure_primary_store_exists(signer::address_of(sender), metadata); // Check if the sender store object has been burnt or not. If so, unburn it first. may_be_unburn(sender, sender_store); let recipient_store = ensure_primary_store_exists(recipient, metadata); @@ -213,34 +237,49 @@ module supra_framework::primary_fungible_store { /// Mint to the primary store of `owner`. public fun mint(mint_ref: &MintRef, owner: address, amount: u64) acquires DeriveRefPod { - let primary_store = ensure_primary_store_exists(owner, fungible_asset::mint_ref_metadata(mint_ref)); + let primary_store = + ensure_primary_store_exists( + owner, fungible_asset::mint_ref_metadata(mint_ref) + ); fungible_asset::mint_to(mint_ref, primary_store, amount); } /// Burn from the primary store of `owner`. public fun burn(burn_ref: &BurnRef, owner: address, amount: u64) { - let primary_store = primary_store(owner, fungible_asset::burn_ref_metadata(burn_ref)); + let primary_store = + primary_store(owner, fungible_asset::burn_ref_metadata(burn_ref)); fungible_asset::burn_from(burn_ref, primary_store, amount); } /// Freeze/Unfreeze the primary store of `owner`. - public fun set_frozen_flag(transfer_ref: &TransferRef, owner: address, frozen: bool) acquires DeriveRefPod { - let primary_store = ensure_primary_store_exists(owner, fungible_asset::transfer_ref_metadata(transfer_ref)); + public fun set_frozen_flag( + transfer_ref: &TransferRef, owner: address, frozen: bool + ) acquires DeriveRefPod { + let primary_store = + ensure_primary_store_exists( + owner, fungible_asset::transfer_ref_metadata(transfer_ref) + ); fungible_asset::set_frozen_flag(transfer_ref, primary_store, frozen); } /// Withdraw from the primary store of `owner` ignoring frozen flag. - public fun withdraw_with_ref(transfer_ref: &TransferRef, owner: address, amount: u64): FungibleAsset { - let from_primary_store = primary_store(owner, fungible_asset::transfer_ref_metadata(transfer_ref)); + public fun withdraw_with_ref( + transfer_ref: &TransferRef, owner: address, amount: u64 + ): FungibleAsset { + let from_primary_store = + primary_store(owner, fungible_asset::transfer_ref_metadata(transfer_ref)); fungible_asset::withdraw_with_ref(transfer_ref, from_primary_store, amount) } /// Deposit from the primary store of `owner` ignoring frozen flag. - public fun deposit_with_ref(transfer_ref: &TransferRef, owner: address, fa: FungibleAsset) acquires DeriveRefPod { - let from_primary_store = ensure_primary_store_exists( - owner, - fungible_asset::transfer_ref_metadata(transfer_ref) - ); + public fun deposit_with_ref( + transfer_ref: &TransferRef, owner: address, fa: FungibleAsset + ) acquires DeriveRefPod { + let from_primary_store = + ensure_primary_store_exists( + owner, + fungible_asset::transfer_ref_metadata(transfer_ref) + ); fungible_asset::deposit_with_ref(transfer_ref, from_primary_store, fa); } @@ -251,9 +290,15 @@ module supra_framework::primary_fungible_store { to: address, amount: u64 ) acquires DeriveRefPod { - let from_primary_store = primary_store(from, fungible_asset::transfer_ref_metadata(transfer_ref)); - let to_primary_store = ensure_primary_store_exists(to, fungible_asset::transfer_ref_metadata(transfer_ref)); - fungible_asset::transfer_with_ref(transfer_ref, from_primary_store, to_primary_store, amount); + let from_primary_store = + primary_store(from, fungible_asset::transfer_ref_metadata(transfer_ref)); + let to_primary_store = + ensure_primary_store_exists( + to, fungible_asset::transfer_ref_metadata(transfer_ref) + ); + fungible_asset::transfer_with_ref( + transfer_ref, from_primary_store, to_primary_store, amount + ); } fun may_be_unburn(owner: &signer, store: Object) { @@ -285,7 +330,7 @@ module supra_framework::primary_fungible_store { string::utf8(b"@T"), 0, string::utf8(b"http://example.com/icon"), - string::utf8(b"http://example.com"), + string::utf8(b"http://example.com") ); let mint_ref = generate_mint_ref(constructor_ref); let burn_ref = generate_burn_ref(constructor_ref); @@ -312,12 +357,10 @@ module supra_framework::primary_fungible_store { } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_basic_flow( - creator: &signer, - aaron: &signer, - ) acquires DeriveRefPod { + fun test_basic_flow(creator: &signer, aaron: &signer) acquires DeriveRefPod { let (creator_ref, metadata) = create_test_token(creator); - let (mint_ref, transfer_ref, burn_ref) = init_test_metadata_with_primary_store_enabled(&creator_ref); + let (mint_ref, transfer_ref, burn_ref) = + init_test_metadata_with_primary_store_enabled(&creator_ref); let creator_address = signer::address_of(creator); let aaron_address = signer::address_of(aaron); assert!(balance(creator_address, metadata) == 0, 1); @@ -341,11 +384,11 @@ module supra_framework::primary_fungible_store { #[test(creator = @0xcafe, aaron = @0xface)] fun test_basic_flow_with_min_balance( - creator: &signer, - aaron: &signer, + creator: &signer, aaron: &signer ) acquires DeriveRefPod { let (creator_ref, metadata) = create_test_token(creator); - let (mint_ref, _transfer_ref, _) = init_test_metadata_with_primary_store_enabled(&creator_ref); + let (mint_ref, _transfer_ref, _) = + init_test_metadata_with_primary_store_enabled(&creator_ref); let creator_address = signer::address_of(creator); let aaron_address = signer::address_of(aaron); assert!(balance(creator_address, metadata) == 0, 1); @@ -359,12 +402,10 @@ module supra_framework::primary_fungible_store { } #[test(user_1 = @0xcafe, user_2 = @0xface)] - fun test_transfer_to_burnt_store( - user_1: &signer, - user_2: &signer, - ) acquires DeriveRefPod { + fun test_transfer_to_burnt_store(user_1: &signer, user_2: &signer) acquires DeriveRefPod { let (creator_ref, metadata) = create_test_token(user_1); - let (mint_ref, _, _) = init_test_metadata_with_primary_store_enabled(&creator_ref); + let (mint_ref, _, _) = + init_test_metadata_with_primary_store_enabled(&creator_ref); let user_1_address = signer::address_of(user_1); let user_2_address = signer::address_of(user_2); mint(&mint_ref, user_1_address, 100); @@ -384,11 +425,11 @@ module supra_framework::primary_fungible_store { #[test(user_1 = @0xcafe, user_2 = @0xface)] fun test_withdraw_from_burnt_store( - user_1: &signer, - user_2: &signer, + user_1: &signer, user_2: &signer ) acquires DeriveRefPod { let (creator_ref, metadata) = create_test_token(user_1); - let (mint_ref, _, _) = init_test_metadata_with_primary_store_enabled(&creator_ref); + let (mint_ref, _, _) = + init_test_metadata_with_primary_store_enabled(&creator_ref); let user_1_address = signer::address_of(user_1); let user_2_address = signer::address_of(user_2); mint(&mint_ref, user_1_address, 100); diff --git a/aptos-move/framework/supra-framework/sources/randomness.move b/aptos-move/framework/supra-framework/sources/randomness.move index 4aa26724473a5..6cfa6e01e734b 100644 --- a/aptos-move/framework/supra-framework/sources/randomness.move +++ b/aptos-move/framework/supra-framework/sources/randomness.move @@ -26,42 +26,46 @@ module supra_framework::randomness { /// `#[randomness]` annotation. Otherwise, malicious users can bias randomness result. const E_API_USE_IS_BIASIBLE: u64 = 1; - const MAX_U256: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935; + const MAX_U256: u256 = + 115792089237316195423570985008687907853269984665640564039457584007913129639935; /// 32-byte randomness seed unique to every block. /// This resource is updated in every block prologue. struct PerBlockRandomness has drop, key { epoch: u64, round: u64, - seed: Option>, + seed: Option> } #[event] /// Event emitted every time a public randomness API in this module is called. - struct RandomnessGeneratedEvent has store, drop { - } + struct RandomnessGeneratedEvent has store, drop {} /// Called in genesis.move. /// Must be called in tests to initialize the `PerBlockRandomness` resource. public fun initialize(framework: &signer) { system_addresses::assert_supra_framework(framework); if (!exists(@supra_framework)) { - move_to(framework, PerBlockRandomness { - epoch: 0, - round: 0, - seed: option::none(), - }); + move_to( + framework, + PerBlockRandomness { epoch: 0, round: 0, seed: option::none() } + ); } } #[test_only] - public fun initialize_for_testing(framework: &signer) acquires PerBlockRandomness { + public fun initialize_for_testing(framework: &signer) acquires PerBlockRandomness { initialize(framework); set_seed(x"0000000000000000000000000000000000000000000000000000000000000000"); } /// Invoked in block prologues to update the block-level randomness seed. - public(friend) fun on_new_block(vm: &signer, epoch: u64, round: u64, seed_for_new_block: Option>) acquires PerBlockRandomness { + public(friend) fun on_new_block( + vm: &signer, + epoch: u64, + round: u64, + seed_for_new_block: Option> + ) acquires PerBlockRandomness { system_addresses::assert_vm(vm); if (exists(@supra_framework)) { let randomness = borrow_global_mut(@supra_framework); @@ -303,7 +307,7 @@ module supra_framework::randomness { let values = vector[]; - if(n == 0) { + if (n == 0) { return vector[] }; @@ -354,17 +358,26 @@ module supra_framework::randomness { let a_clone = a; let neg_b = m - b; let a_less = a < neg_b; - take_first(if (a_less) { a + b } else { a_clone - neg_b }, if (!a_less) { a_clone - neg_b } else { a + b }) + take_first( + if (a_less) { a + b } + else { + a_clone - neg_b + }, + if (!a_less) { + a_clone - neg_b + } else { a + b } + ) } - fun take_first(x: u256, _y: u256 ): u256 { x } + fun take_first(x: u256, _y: u256): u256 { + x + } #[verify_only] fun safe_add_mod_for_verification(a: u256, b: u256, m: u256): u256 { let neg_b = m - b; - if (a < neg_b) { - a + b - } else { + if (a < neg_b) { a + b } + else { a - neg_b } } @@ -385,13 +398,69 @@ module supra_framework::randomness { assert!(2 == safe_add_mod(4, 3, 5), 1); assert!(7 == safe_add_mod(3, 4, 9), 1); assert!(7 == safe_add_mod(4, 3, 9), 1); - assert!(0xfffffffffffffffffffffffffffffffffffffffffffffffe == safe_add_mod(0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0x000000000000000000000000000000000000000000000001, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0xfffffffffffffffffffffffffffffffffffffffffffffffe == safe_add_mod(0x000000000000000000000000000000000000000000000001, 0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0x000000000000000000000000000000000000000000000000 == safe_add_mod(0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0x000000000000000000000000000000000000000000000002, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0x000000000000000000000000000000000000000000000000 == safe_add_mod(0x000000000000000000000000000000000000000000000002, 0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0x000000000000000000000000000000000000000000000001 == safe_add_mod(0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0x000000000000000000000000000000000000000000000003, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0x000000000000000000000000000000000000000000000001 == safe_add_mod(0x000000000000000000000000000000000000000000000003, 0xfffffffffffffffffffffffffffffffffffffffffffffffd, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); - assert!(0xfffffffffffffffffffffffffffffffffffffffffffffffd == safe_add_mod(0xfffffffffffffffffffffffffffffffffffffffffffffffe, 0xfffffffffffffffffffffffffffffffffffffffffffffffe, 0xffffffffffffffffffffffffffffffffffffffffffffffff), 1); + assert!( + 0xfffffffffffffffffffffffffffffffffffffffffffffffe + == safe_add_mod( + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0x000000000000000000000000000000000000000000000001, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0xfffffffffffffffffffffffffffffffffffffffffffffffe + == safe_add_mod( + 0x000000000000000000000000000000000000000000000001, + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0x000000000000000000000000000000000000000000000000 + == safe_add_mod( + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0x000000000000000000000000000000000000000000000002, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0x000000000000000000000000000000000000000000000000 + == safe_add_mod( + 0x000000000000000000000000000000000000000000000002, + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0x000000000000000000000000000000000000000000000001 + == safe_add_mod( + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0x000000000000000000000000000000000000000000000003, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0x000000000000000000000000000000000000000000000001 + == safe_add_mod( + 0x000000000000000000000000000000000000000000000003, + 0xfffffffffffffffffffffffffffffffffffffffffffffffd, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); + assert!( + 0xfffffffffffffffffffffffffffffffffffffffffffffffd + == safe_add_mod( + 0xfffffffffffffffffffffffffffffffffffffffffffffffe, + 0xfffffffffffffffffffffffffffffffffffffffffffffffe, + 0xffffffffffffffffffffffffffffffffffffffffffffffff + ), + 1 + ); } #[test(fx = @supra_framework)] @@ -524,7 +593,7 @@ module supra_framework::randomness { for (i in 0..n) { let bit = vector::borrow(&present, i); - if(*bit == false) { + if (*bit == false) { return false }; }; @@ -559,12 +628,12 @@ module supra_framework::randomness { let permutations = table_with_length::new, bool>(); // This loop will not exit until all permutations are created - while(table_with_length::length(&permutations) < num_permutations) { + while (table_with_length::length(&permutations) < num_permutations) { let v = permutation(size); assert!(vector::length(&v) == size, 0); assert!(is_permutation(&v), 0); - if(table_with_length::contains(&permutations, v) == false) { + if (table_with_length::contains(&permutations, v) == false) { table_with_length::add(&mut permutations, v, true); } }; diff --git a/aptos-move/framework/supra-framework/sources/randomness.spec.move b/aptos-move/framework/supra-framework/sources/randomness.spec.move index ccfc7963bf531..d80a0fef1d147 100644 --- a/aptos-move/framework/supra-framework/sources/randomness.spec.move +++ b/aptos-move/framework/supra-framework/sources/randomness.spec.move @@ -3,7 +3,8 @@ spec supra_framework::randomness { spec module { use supra_framework::chain_status; pragma verify = true; - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); global var: vector; } @@ -29,12 +30,17 @@ spec supra_framework::randomness { aborts_if framework_addr != @supra_framework; } - spec on_new_block(vm: &signer, epoch: u64, round: u64, seed_for_new_block: Option>) { + spec on_new_block( + vm: &signer, epoch: u64, round: u64, seed_for_new_block: Option> + ) { use std::signer; aborts_if signer::address_of(vm) != @vm; - ensures exists(@supra_framework) ==> global(@supra_framework).seed == seed_for_new_block; - ensures exists(@supra_framework) ==> global(@supra_framework).epoch == epoch; - ensures exists(@supra_framework) ==> global(@supra_framework).round == round; + ensures exists(@supra_framework) ==> + global(@supra_framework).seed == seed_for_new_block; + ensures exists(@supra_framework) ==> + global(@supra_framework).epoch == epoch; + ensures exists(@supra_framework) ==> + global(@supra_framework).round == round; } spec next_32_bytes(): vector { @@ -46,7 +52,8 @@ spec supra_framework::randomness { let txn_hash = transaction_context::spec_get_txn_hash(); let txn_counter = spec_fetch_and_increment_txn_counter(); ensures len(result) == 32; - ensures result == hash::sha3_256(concat(concat(concat(input, seed), txn_hash), txn_counter)); + ensures result + == hash::sha3_256(concat(concat(concat(input, seed), txn_hash), txn_counter)); } spec schema NextBlobAbortsIf { @@ -105,7 +112,6 @@ spec supra_framework::randomness { ensures result >= min_incl && result < max_excl; } - spec u64_range(min_incl: u64, max_excl: u64): u64 { pragma verify_duration_estimate = 120; include NextBlobAbortsIf; @@ -134,9 +140,8 @@ spec supra_framework::randomness { } spec fun spec_safe_add_mod(a: u256, b: u256, m: u256): u256 { - if (a < m - b) { - a + b - } else { + if (a < m - b) { a + b } + else { a - (m - b) } } diff --git a/aptos-move/framework/supra-framework/sources/reconfiguration.move b/aptos-move/framework/supra-framework/sources/reconfiguration.move index 9c4b11debea8c..d516e4015f6a6 100644 --- a/aptos-move/framework/supra-framework/sources/reconfiguration.move +++ b/aptos-move/framework/supra-framework/sources/reconfiguration.move @@ -30,7 +30,7 @@ module supra_framework::reconfiguration { /// with new configuration information. This is also called a /// "reconfiguration event" struct NewEpochEvent has drop, store { - epoch: u64, + epoch: u64 } #[event] @@ -38,7 +38,7 @@ module supra_framework::reconfiguration { /// with new configuration information. This is also called a /// "reconfiguration event" struct NewEpoch has drop, store { - epoch: u64, + epoch: u64 } /// Holds information about state of reconfiguration @@ -48,7 +48,7 @@ module supra_framework::reconfiguration { /// Time of last reconfiguration. Only changes on reconfiguration events. last_reconfiguration_time: u64, /// Event handle for reconfiguration events - events: event::EventHandle, + events: event::EventHandle } /// Reconfiguration will be disabled if this resource is published under the @@ -72,13 +72,16 @@ module supra_framework::reconfiguration { system_addresses::assert_supra_framework(supra_framework); // assert it matches `new_epoch_event_key()`, otherwise the event can't be recognized - assert!(account::get_guid_next_creation_num(signer::address_of(supra_framework)) == 2, error::invalid_state(EINVALID_GUID_FOR_EVENT)); + assert!( + account::get_guid_next_creation_num(signer::address_of(supra_framework)) == 2, + error::invalid_state(EINVALID_GUID_FOR_EVENT) + ); move_to( supra_framework, Configuration { epoch: 0, last_reconfiguration_time: 0, - events: account::new_event_handle(supra_framework), + events: account::new_event_handle(supra_framework) } ); } @@ -97,7 +100,9 @@ module supra_framework::reconfiguration { system_addresses::assert_supra_framework(supra_framework); assert!(!reconfiguration_enabled(), error::invalid_state(ECONFIGURATION)); - DisableReconfiguration {} = move_from(signer::address_of(supra_framework)); + DisableReconfiguration {} = move_from( + signer::address_of(supra_framework) + ); } fun reconfiguration_enabled(): bool { @@ -107,9 +112,9 @@ module supra_framework::reconfiguration { /// Signal validators to start using new configuration. Must be called from friend config modules. public(friend) fun reconfigure() acquires Configuration { // Do not do anything if genesis has not finished. - if (chain_status::is_genesis() || timestamp::now_microseconds() == 0 || !reconfiguration_enabled()) { - return - }; + if (chain_status::is_genesis() + || timestamp::now_microseconds() == 0 + || !reconfiguration_enabled()) { return }; let config_ref = borrow_global_mut(@supra_framework); let current_time = timestamp::now_microseconds(); @@ -126,9 +131,7 @@ module supra_framework::reconfiguration { // Thus, this check ensures that a transaction that does multiple "reconfiguration required" actions emits only // one reconfiguration event. // - if (current_time == config_ref.last_reconfiguration_time) { - return - }; + if (current_time == config_ref.last_reconfiguration_time) { return }; reconfiguration_state::on_reconfig_start(); @@ -150,7 +153,10 @@ module supra_framework::reconfiguration { stake::on_new_epoch(); storage_gas::on_reconfig(); - assert!(current_time > config_ref.last_reconfiguration_time, error::invalid_state(EINVALID_BLOCK_TIME)); + assert!( + current_time > config_ref.last_reconfiguration_time, + error::invalid_state(EINVALID_BLOCK_TIME) + ); config_ref.last_reconfiguration_time = current_time; spec { assume config_ref.epoch + 1 <= MAX_U64; @@ -159,16 +165,12 @@ module supra_framework::reconfiguration { if (std::features::module_event_migration_enabled()) { event::emit( - NewEpoch { - epoch: config_ref.epoch, - }, + NewEpoch { epoch: config_ref.epoch } ); }; event::emit_event( &mut config_ref.events, - NewEpochEvent { - epoch: config_ref.epoch, - }, + NewEpochEvent { epoch: config_ref.epoch } ); reconfiguration_state::on_reconfig_finish(); @@ -186,22 +188,21 @@ module supra_framework::reconfiguration { /// reconfiguration event. fun emit_genesis_reconfiguration_event() acquires Configuration { let config_ref = borrow_global_mut(@supra_framework); - assert!(config_ref.epoch == 0 && config_ref.last_reconfiguration_time == 0, error::invalid_state(ECONFIGURATION)); + assert!( + config_ref.epoch == 0 && config_ref.last_reconfiguration_time == 0, + error::invalid_state(ECONFIGURATION) + ); config_ref.epoch = 1; config_ref.last_reconfiguration_time = timestamp::now_microseconds(); if (std::features::module_event_migration_enabled()) { event::emit( - NewEpoch { - epoch: config_ref.epoch, - }, + NewEpoch { epoch: config_ref.epoch } ); }; event::emit_event( &mut config_ref.events, - NewEpochEvent { - epoch: config_ref.epoch, - }, + NewEpochEvent { epoch: config_ref.epoch } ); } @@ -214,7 +215,7 @@ module supra_framework::reconfiguration { Configuration { epoch: 0, last_reconfiguration_time: 0, - events: account::new_event_handle(account), + events: account::new_event_handle(account) } ); } @@ -230,9 +231,7 @@ module supra_framework::reconfiguration { public fun reconfigure_for_test_custom() acquires Configuration { let config_ref = borrow_global_mut(@supra_framework); let current_time = timestamp::now_microseconds(); - if (current_time == config_ref.last_reconfiguration_time) { - return - }; + if (current_time == config_ref.last_reconfiguration_time) { return }; config_ref.last_reconfiguration_time = current_time; config_ref.epoch = config_ref.epoch + 1; } diff --git a/aptos-move/framework/supra-framework/sources/reconfiguration.spec.move b/aptos-move/framework/supra-framework/sources/reconfiguration.spec.move index 8174f259d761d..4c2670e8edec8 100644 --- a/aptos-move/framework/supra-framework/sources/reconfiguration.spec.move +++ b/aptos-move/framework/supra-framework/sources/reconfiguration.spec.move @@ -47,7 +47,8 @@ spec supra_framework::reconfiguration { pragma aborts_if_is_strict; // After genesis, `Configuration` exists. - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); invariant [suspendable] chain_status::is_operating() ==> (timestamp::spec_now_microseconds() >= last_reconfiguration_time()); } @@ -79,15 +80,13 @@ spec supra_framework::reconfiguration { /// [high-level-req-1] ensures exists(@supra_framework); ensures config.epoch == 0 && config.last_reconfiguration_time == 0; - ensures config.events == event::EventHandle { - counter: 0, - guid: guid::GUID { - id: guid::ID { - creation_num: 2, - addr: @supra_framework + ensures config.events + == event::EventHandle { + counter: 0, + guid: guid::GUID { + id: guid::ID { creation_num: 2, addr: @supra_framework } } - } - }; + }; } spec current_epoch(): u64 { @@ -122,7 +121,8 @@ spec supra_framework::reconfiguration { spec last_reconfiguration_time { aborts_if !exists(@supra_framework); - ensures result == global(@supra_framework).last_reconfiguration_time; + ensures result + == global(@supra_framework).last_reconfiguration_time; } spec reconfigure { @@ -135,9 +135,15 @@ spec supra_framework::reconfiguration { pragma verify_duration_estimate = 600; requires exists(@supra_framework); - let success = !(chain_status::is_genesis() || timestamp::spec_now_microseconds() == 0 || !reconfiguration_enabled()) - && timestamp::spec_now_microseconds() != global(@supra_framework).last_reconfiguration_time; - include features::spec_periodical_reward_rate_decrease_enabled() ==> staking_config::StakingRewardsConfigEnabledRequirement; + let success = !( + chain_status::is_genesis() + || timestamp::spec_now_microseconds() == 0 + || !reconfiguration_enabled() + ) + && timestamp::spec_now_microseconds() + != global(@supra_framework).last_reconfiguration_time; + include features::spec_periodical_reward_rate_decrease_enabled() ==> + staking_config::StakingRewardsConfigEnabledRequirement; include success ==> supra_coin::ExistsSupraCoin; include transaction_fee::RequiresCollectedFeesPerValueLeqBlockAptosSupply; aborts_if false; @@ -145,15 +151,21 @@ spec supra_framework::reconfiguration { // but its existing ensure conditions satisfy hp. // The property below is not proved within 500s and still cause an timeout // property 3: Synchronization of NewEpochEvent counter with configuration epoch. - ensures success ==> global(@supra_framework).epoch == old(global(@supra_framework).epoch) + 1; - ensures success ==> global(@supra_framework).last_reconfiguration_time == timestamp::spec_now_microseconds(); + ensures success ==> + global(@supra_framework).epoch + == old(global(@supra_framework).epoch) + 1; + ensures success ==> + global(@supra_framework).last_reconfiguration_time + == timestamp::spec_now_microseconds(); // We remove the ensures of event increment due to inconsisency // TODO: property 4: Only performs reconfiguration if genesis has started and reconfiguration is enabled. // Also, the last reconfiguration must not be the current time, returning early without further actions otherwise. // property 5: Consecutive reconfigurations without the passage of time are not permitted. /// [high-level-req-4] /// [high-level-req-5] - ensures !success ==> global(@supra_framework).epoch == old(global(@supra_framework).epoch); + ensures !success ==> + global(@supra_framework).epoch + == old(global(@supra_framework).epoch); } spec reconfiguration_enabled { diff --git a/aptos-move/framework/supra-framework/sources/reconfiguration_state.move b/aptos-move/framework/supra-framework/sources/reconfiguration_state.move index 64375b6f8ec5b..9383f44de5289 100644 --- a/aptos-move/framework/supra-framework/sources/reconfiguration_state.move +++ b/aptos-move/framework/supra-framework/sources/reconfiguration_state.move @@ -21,7 +21,7 @@ module supra_framework::reconfiguration_state { /// Currently the variant type is one of the following. /// - `ReconfigStateInactive` /// - `ReconfigStateActive` - variant: Any, + variant: Any } /// A state variant indicating no reconfiguration is in progress. @@ -29,7 +29,7 @@ module supra_framework::reconfiguration_state { /// A state variant indicating a reconfiguration is in progress. struct StateActive has copy, drop, store { - start_time_secs: u64, + start_time_secs: u64 } public fun is_initialized(): bool { @@ -39,9 +39,12 @@ module supra_framework::reconfiguration_state { public fun initialize(fx: &signer) { system_addresses::assert_supra_framework(fx); if (!exists(@supra_framework)) { - move_to(fx, State { - variant: copyable_any::pack(StateInactive {}) - }) + move_to( + fx, + State { + variant: copyable_any::pack(StateInactive {}) + } + ) } } @@ -67,11 +70,12 @@ module supra_framework::reconfiguration_state { public(friend) fun on_reconfig_start() acquires State { if (exists(@supra_framework)) { let state = borrow_global_mut(@supra_framework); - let variant_type_name = *string::bytes(copyable_any::type_name(&state.variant)); + let variant_type_name = + *string::bytes(copyable_any::type_name(&state.variant)); if (variant_type_name == b"0x1::reconfiguration_state::StateInactive") { - state.variant = copyable_any::pack(StateActive { - start_time_secs: timestamp::now_seconds() - }); + state.variant = copyable_any::pack( + StateActive { start_time_secs: timestamp::now_seconds() } + ); } }; } @@ -94,7 +98,8 @@ module supra_framework::reconfiguration_state { public(friend) fun on_reconfig_finish() acquires State { if (exists(@supra_framework)) { let state = borrow_global_mut(@supra_framework); - let variant_type_name = *string::bytes(copyable_any::type_name(&state.variant)); + let variant_type_name = + *string::bytes(copyable_any::type_name(&state.variant)); if (variant_type_name == b"0x1::reconfiguration_state::StateActive") { state.variant = copyable_any::pack(StateInactive {}); } else { diff --git a/aptos-move/framework/supra-framework/sources/reconfiguration_state.spec.move b/aptos-move/framework/supra-framework/sources/reconfiguration_state.spec.move index 8b6d175e2c23f..635332d39a9b0 100644 --- a/aptos-move/framework/supra-framework/sources/reconfiguration_state.spec.move +++ b/aptos-move/framework/supra-framework/sources/reconfiguration_state.spec.move @@ -2,7 +2,8 @@ spec supra_framework::reconfiguration_state { spec module { use supra_framework::chain_status; - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); } spec initialize(fx: &signer) { @@ -11,7 +12,8 @@ spec supra_framework::reconfiguration_state { aborts_if signer::address_of(fx) != @supra_framework; let post post_state = global(@supra_framework); ensures exists(@supra_framework); - ensures !exists(@supra_framework) ==> from_bcs::deserializable(post_state.variant.data); + ensures !exists(@supra_framework) ==> + from_bcs::deserializable(post_state.variant.data); } spec initialize_for_testing(fx: &signer) { @@ -24,25 +26,31 @@ spec supra_framework::reconfiguration_state { } spec fun spec_is_in_progress(): bool { - if (!exists(@supra_framework)) { - false - } else { - copyable_any::type_name(global(@supra_framework).variant).bytes == b"0x1::reconfiguration_state::StateActive" + if (!exists(@supra_framework)) { false } + else { + copyable_any::type_name(global(@supra_framework).variant).bytes + == b"0x1::reconfiguration_state::StateActive" } } spec State { use aptos_std::from_bcs; use aptos_std::type_info; - invariant copyable_any::type_name(variant).bytes == b"0x1::reconfiguration_state::StateActive" || - copyable_any::type_name(variant).bytes == b"0x1::reconfiguration_state::StateInactive"; - invariant copyable_any::type_name(variant).bytes == b"0x1::reconfiguration_state::StateActive" - ==> from_bcs::deserializable(variant.data); - invariant copyable_any::type_name(variant).bytes == b"0x1::reconfiguration_state::StateInactive" - ==> from_bcs::deserializable(variant.data); - invariant copyable_any::type_name(variant).bytes == b"0x1::reconfiguration_state::StateActive" ==> + invariant copyable_any::type_name(variant).bytes + == b"0x1::reconfiguration_state::StateActive" + || copyable_any::type_name(variant).bytes + == b"0x1::reconfiguration_state::StateInactive"; + invariant copyable_any::type_name(variant).bytes + == b"0x1::reconfiguration_state::StateActive" ==> + from_bcs::deserializable(variant.data); + invariant copyable_any::type_name(variant).bytes + == b"0x1::reconfiguration_state::StateInactive" ==> + from_bcs::deserializable(variant.data); + invariant copyable_any::type_name(variant).bytes + == b"0x1::reconfiguration_state::StateActive" ==> type_info::type_name() == variant.type_name; - invariant copyable_any::type_name(variant).bytes == b"0x1::reconfiguration_state::StateInactive" ==> + invariant copyable_any::type_name(variant).bytes + == b"0x1::reconfiguration_state::StateInactive" ==> type_info::type_name() == variant.type_name; } @@ -54,19 +62,31 @@ spec supra_framework::reconfiguration_state { requires exists(@supra_framework); let state = Any { type_name: type_info::type_name(), - data: bcs::serialize(StateActive { - start_time_secs: timestamp::spec_now_seconds() - }) + data: bcs::serialize( + StateActive { start_time_secs: timestamp::spec_now_seconds() } + ) }; let pre_state = global(@supra_framework); let post post_state = global(@supra_framework); - ensures (exists(@supra_framework) && copyable_any::type_name(pre_state.variant).bytes - == b"0x1::reconfiguration_state::StateInactive") ==> copyable_any::type_name(post_state.variant).bytes - == b"0x1::reconfiguration_state::StateActive"; - ensures (exists(@supra_framework) && copyable_any::type_name(pre_state.variant).bytes - == b"0x1::reconfiguration_state::StateInactive") ==> post_state.variant == state; - ensures (exists(@supra_framework) && copyable_any::type_name(pre_state.variant).bytes - == b"0x1::reconfiguration_state::StateInactive") ==> from_bcs::deserializable(post_state.variant.data); + ensures ( + exists(@supra_framework) + && copyable_any::type_name(pre_state.variant).bytes + == b"0x1::reconfiguration_state::StateInactive" + ) ==> + copyable_any::type_name(post_state.variant).bytes + == b"0x1::reconfiguration_state::StateActive"; + ensures ( + exists(@supra_framework) + && copyable_any::type_name(pre_state.variant).bytes + == b"0x1::reconfiguration_state::StateInactive" + ) ==> + post_state.variant == state; + ensures ( + exists(@supra_framework) + && copyable_any::type_name(pre_state.variant).bytes + == b"0x1::reconfiguration_state::StateInactive" + ) ==> + from_bcs::deserializable(post_state.variant.data); } spec start_time_secs(): u64 { @@ -84,7 +104,7 @@ spec supra_framework::reconfiguration_state { requires copyable_any::type_name(global(@supra_framework).variant).bytes == b"0x1::reconfiguration_state::StateActive"; include UnpackRequiresStateActive { - x: global(@supra_framework).variant + x: global(@supra_framework).variant }; } @@ -92,18 +112,18 @@ spec supra_framework::reconfiguration_state { use aptos_std::from_bcs; use aptos_std::type_info; x: Any; - requires type_info::type_name() == x.type_name && from_bcs::deserializable(x.data); + requires type_info::type_name() == x.type_name + && from_bcs::deserializable(x.data); } spec schema StartTimeSecsAbortsIf { aborts_if !exists(@supra_framework); - include copyable_any::type_name(global(@supra_framework).variant).bytes + include copyable_any::type_name(global(@supra_framework).variant).bytes == b"0x1::reconfiguration_state::StateActive" ==> - copyable_any::UnpackAbortsIf { - x: global(@supra_framework).variant - }; + copyable_any::UnpackAbortsIf { + x: global(@supra_framework).variant + }; aborts_if copyable_any::type_name(global(@supra_framework).variant).bytes != b"0x1::reconfiguration_state::StateActive"; } - } diff --git a/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.move b/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.move index d8bfe8ee31180..fc2157c463a67 100644 --- a/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.move +++ b/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.move @@ -36,7 +36,7 @@ module supra_framework::reconfiguration_with_dkg { cur_epoch, randomness_config::current(), stake::cur_validator_consensus_infos(), - stake::next_validator_consensus_infos(), + stake::next_validator_consensus_infos() ); } diff --git a/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.spec.move b/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.spec.move index d1ca7d47e204e..4f9a6e467dca8 100644 --- a/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.spec.move +++ b/aptos-move/framework/supra-framework/sources/reconfiguration_with_dkg.spec.move @@ -12,8 +12,8 @@ spec supra_framework::reconfiguration_with_dkg { requires chain_status::is_operating(); include stake::ResourceRequirement; include stake::GetReconfigStartTimeRequirement; - include features::spec_periodical_reward_rate_decrease_enabled( - ) ==> staking_config::StakingRewardsConfigEnabledRequirement; + include features::spec_periodical_reward_rate_decrease_enabled() ==> + staking_config::StakingRewardsConfigEnabledRequirement; aborts_if false; pragma verify_duration_estimate = 600; // TODO: set because of timeout (property proved). } @@ -68,9 +68,7 @@ spec supra_framework::reconfiguration_with_dkg { spec finish_with_dkg_result(account: &signer, dkg_result: vector) { use supra_framework::dkg; pragma verify_duration_estimate = 1500; - include FinishRequirement { - framework: account - }; + include FinishRequirement { framework: account }; requires dkg::has_incomplete_session(); aborts_if false; } diff --git a/aptos-move/framework/supra-framework/sources/resource_account.move b/aptos-move/framework/supra-framework/sources/resource_account.move index afb124eb939df..3e9997944745b 100644 --- a/aptos-move/framework/supra-framework/sources/resource_account.move +++ b/aptos-move/framework/supra-framework/sources/resource_account.move @@ -77,7 +77,7 @@ module supra_framework::resource_account { const ZERO_AUTH_KEY: vector = x"0000000000000000000000000000000000000000000000000000000000000000"; struct Container has key { - store: SimpleMap, + store: SimpleMap } /// Creates a new resource account and rotates the authentication key to either @@ -86,14 +86,15 @@ module supra_framework::resource_account { public entry fun create_resource_account( origin: &signer, seed: vector, - optional_auth_key: vector, + optional_auth_key: vector ) acquires Container { - let (resource, resource_signer_cap) = account::create_resource_account(origin, seed); + let (resource, resource_signer_cap) = + account::create_resource_account(origin, seed); rotate_account_authentication_key_and_store_capability( origin, resource, resource_signer_cap, - optional_auth_key, + optional_auth_key ); } @@ -106,16 +107,17 @@ module supra_framework::resource_account { origin: &signer, seed: vector, optional_auth_key: vector, - fund_amount: u64, + fund_amount: u64 ) acquires Container { - let (resource, resource_signer_cap) = account::create_resource_account(origin, seed); + let (resource, resource_signer_cap) = + account::create_resource_account(origin, seed); coin::register(&resource); coin::transfer(origin, signer::address_of(&resource), fund_amount); rotate_account_authentication_key_and_store_capability( origin, resource, resource_signer_cap, - optional_auth_key, + optional_auth_key ); } @@ -125,15 +127,16 @@ module supra_framework::resource_account { origin: &signer, seed: vector, metadata_serialized: vector, - code: vector>, + code: vector> ) acquires Container { - let (resource, resource_signer_cap) = account::create_resource_account(origin, seed); + let (resource, resource_signer_cap) = + account::create_resource_account(origin, seed); supra_framework::code::publish_package_txn(&resource, metadata_serialized, code); rotate_account_authentication_key_and_store_capability( origin, resource, resource_signer_cap, - ZERO_AUTH_KEY, + ZERO_AUTH_KEY ); } @@ -141,7 +144,7 @@ module supra_framework::resource_account { origin: &signer, resource: signer, resource_signer_cap: account::SignerCapability, - optional_auth_key: vector, + optional_auth_key: vector ) acquires Container { let origin_addr = signer::address_of(origin); if (!exists(origin_addr)) { @@ -152,11 +155,12 @@ module supra_framework::resource_account { let resource_addr = signer::address_of(&resource); simple_map::add(&mut container.store, resource_addr, resource_signer_cap); - let auth_key = if (vector::is_empty(&optional_auth_key)) { - account::get_authentication_key(origin_addr) - } else { - optional_auth_key - }; + let auth_key = + if (vector::is_empty(&optional_auth_key)) { + account::get_authentication_key(origin_addr) + } else { + optional_auth_key + }; account::rotate_authentication_key_internal(&resource, auth_key); } @@ -164,10 +168,11 @@ module supra_framework::resource_account { /// account and rotate the account's auth key to 0x0 making the account inaccessible without /// the SignerCapability. public fun retrieve_resource_account_cap( - resource: &signer, - source_addr: address, + resource: &signer, source_addr: address ): account::SignerCapability acquires Container { - assert!(exists(source_addr), error::not_found(ECONTAINER_NOT_PUBLISHED)); + assert!( + exists(source_addr), error::not_found(ECONTAINER_NOT_PUBLISHED) + ); let resource_addr = signer::address_of(resource); let (resource_signer_cap, empty_container) = { @@ -176,7 +181,8 @@ module supra_framework::resource_account { simple_map::contains_key(&container.store, &resource_addr), error::invalid_argument(EUNAUTHORIZED_NOT_OWNER) ); - let (_resource_addr, signer_cap) = simple_map::remove(&mut container.store, &resource_addr); + let (_resource_addr, signer_cap) = + simple_map::remove(&mut container.store, &resource_addr); (signer_cap, simple_map::length(&container.store) == 0) }; @@ -200,7 +206,8 @@ module supra_framework::resource_account { create_resource_account(&user, copy seed, vector::empty()); let container = borrow_global(user_addr); - let resource_addr = supra_framework::account::create_resource_address(&user_addr, seed); + let resource_addr = + supra_framework::account::create_resource_address(&user_addr, seed); let resource_cap = simple_map::borrow(&container.store, &resource_addr); let resource = account::create_signer_with_capability(resource_cap); @@ -209,7 +216,9 @@ module supra_framework::resource_account { #[test(user = @0x1111)] #[expected_failure(abort_code = 393217, location = Self)] - public entry fun test_create_account_and_retrieve_wrong_cap_should_fail(user: signer) acquires Container { + public entry fun test_create_account_and_retrieve_wrong_cap_should_fail( + user: signer + ) acquires Container { let user_addr = signer::address_of(&user); account::create_account(user_addr); @@ -218,7 +227,8 @@ module supra_framework::resource_account { create_resource_account(&user, copy seed, vector::empty()); let container = borrow_global(user_addr); - let resource_addr = supra_framework::account::create_resource_address(&user_addr, seed); + let resource_addr = + supra_framework::account::create_resource_address(&user_addr, seed); let resource_cap = simple_map::borrow(&container.store, &resource_addr); let resource = account::create_signer_with_capability(resource_cap); @@ -258,7 +268,8 @@ module supra_framework::resource_account { let seed = x"01"; create_resource_account_and_fund(&user, copy seed, vector::empty(), 10); - let resource_addr = supra_framework::account::create_resource_address(&user_addr, seed); + let resource_addr = + supra_framework::account::create_resource_address(&user_addr, seed); coin::transfer(&user, resource_addr, 10); coin::destroy_burn_cap(burn); @@ -275,7 +286,8 @@ module supra_framework::resource_account { let seed = x"01"; create_resource_account(&user, copy seed, vector::empty()); - let resource_addr = supra_framework::account::create_resource_address(&user_addr, seed); + let resource_addr = + supra_framework::account::create_resource_address(&user_addr, seed); let coin = coin::mint(100, &mint); coin::deposit(resource_addr, coin); diff --git a/aptos-move/framework/supra-framework/sources/resource_account.spec.move b/aptos-move/framework/supra-framework/sources/resource_account.spec.move index bdd2dca1c0b24..7442f5cb0f562 100644 --- a/aptos-move/framework/supra-framework/sources/resource_account.spec.move +++ b/aptos-move/framework/supra-framework/sources/resource_account.spec.move @@ -64,9 +64,7 @@ spec supra_framework::resource_account { } spec create_resource_account( - origin: &signer, - seed: vector, - optional_auth_key: vector, + origin: &signer, seed: vector, optional_auth_key: vector ) { let source_addr = signer::address_of(origin); let resource_addr = account::spec_create_resource_address(source_addr, seed); @@ -74,10 +72,7 @@ spec supra_framework::resource_account { } spec create_resource_account_and_fund( - origin: &signer, - seed: vector, - optional_auth_key: vector, - fund_amount: u64, + origin: &signer, seed: vector, optional_auth_key: vector, fund_amount: u64 ) { use supra_framework::supra_account; // TODO(fa_migration) @@ -86,12 +81,16 @@ spec supra_framework::resource_account { let resource_addr = account::spec_create_resource_address(source_addr, seed); let coin_store_resource = global>(resource_addr); - include supra_account::WithdrawAbortsIf{from: origin, amount: fund_amount}; - include supra_account::GuidAbortsIf{to: resource_addr}; + include supra_account::WithdrawAbortsIf { + from: origin, + amount: fund_amount + }; + include supra_account::GuidAbortsIf { to: resource_addr }; include RotateAccountAuthenticationKeyAndStoreCapabilityAbortsIfWithoutAccountLimit; //coin property - aborts_if coin::spec_is_account_registered(resource_addr) && coin_store_resource.frozen; + aborts_if coin::spec_is_account_registered(resource_addr) + && coin_store_resource.frozen; /// [high-level-req-3] ensures exists>(resource_addr); } @@ -100,7 +99,7 @@ spec supra_framework::resource_account { origin: &signer, seed: vector, metadata_serialized: vector, - code: vector>, + code: vector> ) { pragma verify = false; //TODO: Loop in code.spec @@ -114,7 +113,7 @@ spec supra_framework::resource_account { origin: &signer, resource: signer, resource_signer_cap: account::SignerCapability, - optional_auth_key: vector, + optional_auth_key: vector ) { let resource_addr = signer::address_of(resource); /// [high-level-req-1] @@ -123,7 +122,8 @@ spec supra_framework::resource_account { ensures exists(signer::address_of(origin)); /// [high-level-req-5] ensures vector::length(optional_auth_key) != 0 ==> - global(resource_addr).authentication_key == optional_auth_key; + global(resource_addr).authentication_key + == optional_auth_key; } spec schema RotateAccountAuthenticationKeyAndStoreCapabilityAbortsIf { @@ -138,11 +138,20 @@ spec supra_framework::resource_account { aborts_if get && !exists(source_addr); /// [high-level-req-4] - aborts_if exists(source_addr) && simple_map::spec_contains_key(container.store, resource_addr); - aborts_if get && !(exists(resource_addr) && len(global(source_addr).authentication_key) == 32); - aborts_if !get && !(exists(resource_addr) && len(optional_auth_key) == 32); - - ensures simple_map::spec_contains_key(global(source_addr).store, resource_addr); + aborts_if exists(source_addr) + && simple_map::spec_contains_key(container.store, resource_addr); + aborts_if get + && !( + exists(resource_addr) + && len(global(source_addr).authentication_key) == 32 + ); + aborts_if !get + && !(exists(resource_addr) + && len(optional_auth_key) == 32); + + ensures simple_map::spec_contains_key( + global(source_addr).store, resource_addr + ); ensures exists(source_addr); } @@ -158,22 +167,25 @@ spec supra_framework::resource_account { requires source_addr != resource_addr; aborts_if len(ZERO_AUTH_KEY) != 32; - include account::exists_at(resource_addr) ==> account::CreateResourceAccountAbortsIf; - include !account::exists_at(resource_addr) ==> account::CreateAccountAbortsIf {addr: resource_addr}; + include account::exists_at(resource_addr) ==> + account::CreateResourceAccountAbortsIf; + include !account::exists_at(resource_addr) ==> + account::CreateAccountAbortsIf { addr: resource_addr }; aborts_if get && !exists(source_addr); - aborts_if exists(source_addr) && simple_map::spec_contains_key(container.store, resource_addr); - aborts_if get && len(global(source_addr).authentication_key) != 32; + aborts_if exists(source_addr) + && simple_map::spec_contains_key(container.store, resource_addr); + aborts_if get + && len(global(source_addr).authentication_key) != 32; aborts_if !get && len(optional_auth_key) != 32; - ensures simple_map::spec_contains_key(global(source_addr).store, resource_addr); + ensures simple_map::spec_contains_key( + global(source_addr).store, resource_addr + ); ensures exists(source_addr); } - spec retrieve_resource_account_cap( - resource: &signer, - source_addr: address, - ) : account::SignerCapability { + spec retrieve_resource_account_cap(resource: &signer, source_addr: address): account::SignerCapability { /// [high-level-req-6] aborts_if !exists(source_addr); let resource_addr = signer::address_of(resource); @@ -183,8 +195,13 @@ spec supra_framework::resource_account { aborts_if !simple_map::spec_contains_key(container.store, resource_addr); aborts_if !exists(resource_addr); /// [high-level-req-8] - ensures simple_map::spec_contains_key(old(global(source_addr)).store, resource_addr) && - simple_map::spec_len(old(global(source_addr)).store) == 1 ==> !exists(source_addr); - ensures exists(source_addr) ==> !simple_map::spec_contains_key(global(source_addr).store, resource_addr); + ensures simple_map::spec_contains_key( + old(global(source_addr)).store, resource_addr + ) && simple_map::spec_len(old(global(source_addr)).store) == 1 ==> + !exists(source_addr); + ensures exists(source_addr) ==> + !simple_map::spec_contains_key( + global(source_addr).store, resource_addr + ); } } diff --git a/aptos-move/framework/supra-framework/sources/stake.move b/aptos-move/framework/supra-framework/sources/stake.move index 2f3e669f6c232..866a8922e9f3b 100644 --- a/aptos-move/framework/supra-framework/sources/stake.move +++ b/aptos-move/framework/supra-framework/sources/stake.move @@ -101,7 +101,7 @@ module supra_framework::stake { /// Having this be separate from the signer for the account that the validator resources are hosted at allows /// modules to have control over a validator. struct OwnerCapability has key, store { - pool_address: address, + pool_address: address } /// Each validator has a separate StakePool resource and can provide a stake. @@ -141,13 +141,14 @@ module supra_framework::stake { add_stake_events: EventHandle, reactivate_stake_events: EventHandle, rotate_consensus_key_events: EventHandle, - update_network_and_fullnode_addresses_events: EventHandle, + update_network_and_fullnode_addresses_events: EventHandle< + UpdateNetworkAndFullnodeAddressesEvent>, increase_lockup_events: EventHandle, join_validator_set_events: EventHandle, distribute_rewards_events: EventHandle, unlock_stake_events: EventHandle, withdraw_stake_events: EventHandle, - leave_validator_set_events: EventHandle, + leave_validator_set_events: EventHandle } /// Validator info stored in validator address. @@ -157,14 +158,14 @@ module supra_framework::stake { // to make it compatible with previous definition, remove later fullnode_addresses: vector, // Index in the active set if the validator corresponding to this stake pool is active. - validator_index: u64, + validator_index: u64 } /// Consensus information per validator, stored in ValidatorSet. struct ValidatorInfo has copy, store, drop { addr: address, voting_power: u64, - config: ValidatorConfig, + config: ValidatorConfig } /// Full ValidatorSet, stored in @supra_framework. @@ -182,79 +183,79 @@ module supra_framework::stake { // Current total voting power. total_voting_power: u128, // Total voting power waiting to join in the next epoch. - total_joining_power: u128, + total_joining_power: u128 } /// SupraCoin capabilities, set during genesis and stored in @CoreResource account. /// This allows the Stake module to mint rewards to stakers. struct SupraCoinCapabilities has key { - mint_cap: MintCapability, + mint_cap: MintCapability } struct IndividualValidatorPerformance has store, drop { successful_proposals: u64, - failed_proposals: u64, + failed_proposals: u64 } struct ValidatorPerformance has key { - validators: vector, + validators: vector } struct RegisterValidatorCandidateEvent has drop, store { - pool_address: address, + pool_address: address } #[event] struct RegisterValidatorCandidate has drop, store { - pool_address: address, + pool_address: address } struct SetOperatorEvent has drop, store { pool_address: address, old_operator: address, - new_operator: address, + new_operator: address } #[event] struct SetOperator has drop, store { pool_address: address, old_operator: address, - new_operator: address, + new_operator: address } struct AddStakeEvent has drop, store { pool_address: address, - amount_added: u64, + amount_added: u64 } #[event] struct AddStake has drop, store { pool_address: address, - amount_added: u64, + amount_added: u64 } struct ReactivateStakeEvent has drop, store { pool_address: address, - amount: u64, + amount: u64 } #[event] struct ReactivateStake has drop, store { pool_address: address, - amount: u64, + amount: u64 } struct RotateConsensusKeyEvent has drop, store { pool_address: address, old_consensus_pubkey: vector, - new_consensus_pubkey: vector, + new_consensus_pubkey: vector } #[event] struct RotateConsensusKey has drop, store { pool_address: address, old_consensus_pubkey: vector, - new_consensus_pubkey: vector, + new_consensus_pubkey: vector } struct UpdateNetworkAndFullnodeAddressesEvent has drop, store { @@ -262,7 +263,7 @@ module supra_framework::stake { old_network_addresses: vector, new_network_addresses: vector, old_fullnode_addresses: vector, - new_fullnode_addresses: vector, + new_fullnode_addresses: vector } #[event] @@ -271,77 +272,77 @@ module supra_framework::stake { old_network_addresses: vector, new_network_addresses: vector, old_fullnode_addresses: vector, - new_fullnode_addresses: vector, + new_fullnode_addresses: vector } struct IncreaseLockupEvent has drop, store { pool_address: address, old_locked_until_secs: u64, - new_locked_until_secs: u64, + new_locked_until_secs: u64 } #[event] struct IncreaseLockup has drop, store { pool_address: address, old_locked_until_secs: u64, - new_locked_until_secs: u64, + new_locked_until_secs: u64 } struct JoinValidatorSetEvent has drop, store { - pool_address: address, + pool_address: address } #[event] struct JoinValidatorSet has drop, store { - pool_address: address, + pool_address: address } struct DistributeRewardsEvent has drop, store { pool_address: address, - rewards_amount: u64, + rewards_amount: u64 } #[event] struct DistributeRewards has drop, store { pool_address: address, - rewards_amount: u64, + rewards_amount: u64 } struct UnlockStakeEvent has drop, store { pool_address: address, - amount_unlocked: u64, + amount_unlocked: u64 } #[event] struct UnlockStake has drop, store { pool_address: address, - amount_unlocked: u64, + amount_unlocked: u64 } struct WithdrawStakeEvent has drop, store { pool_address: address, - amount_withdrawn: u64, + amount_withdrawn: u64 } #[event] struct WithdrawStake has drop, store { pool_address: address, - amount_withdrawn: u64, + amount_withdrawn: u64 } struct LeaveValidatorSetEvent has drop, store { - pool_address: address, + pool_address: address } #[event] struct LeaveValidatorSet has drop, store { - pool_address: address, + pool_address: address } /// Stores transaction fees assigned to validators. All fees are distributed to validators /// at the end of the epoch. struct ValidatorFees has key { - fees_table: Table>, + fees_table: Table> } /// Initializes the resource storing information about collected transaction fees per validator. @@ -356,8 +357,11 @@ module supra_framework::stake { } /// Stores the transaction fee collected to the specified validator address. - public(friend) fun add_transaction_fee(validator_addr: address, fee: Coin) acquires ValidatorFees { - let fees_table = &mut borrow_global_mut(@supra_framework).fees_table; + public(friend) fun add_transaction_fee( + validator_addr: address, fee: Coin + ) acquires ValidatorFees { + let fees_table = + &mut borrow_global_mut(@supra_framework).fees_table; if (table::contains(fees_table, validator_addr)) { let collected_fee = table::borrow_mut(fees_table, validator_addr); coin::merge(collected_fee, fee); @@ -380,9 +384,8 @@ module supra_framework::stake { public fun get_remaining_lockup_secs(pool_address: address): u64 acquires StakePool { assert_stake_pool_exists(pool_address); let lockup_time = borrow_global(pool_address).locked_until_secs; - if (lockup_time <= timestamp::now_seconds()) { - 0 - } else { + if (lockup_time <= timestamp::now_seconds()) { 0 } + else { lockup_time - timestamp::now_seconds() } } @@ -397,7 +400,7 @@ module supra_framework::stake { coin::value(&stake_pool.active), coin::value(&stake_pool.inactive), coin::value(&stake_pool.pending_active), - coin::value(&stake_pool.pending_inactive), + coin::value(&stake_pool.pending_inactive) ) } @@ -407,9 +410,13 @@ module supra_framework::stake { let validator_set = borrow_global(@supra_framework); if (option::is_some(&find_validator(&validator_set.pending_active, pool_address))) { VALIDATOR_STATUS_PENDING_ACTIVE - } else if (option::is_some(&find_validator(&validator_set.active_validators, pool_address))) { + } else if (option::is_some( + &find_validator(&validator_set.active_validators, pool_address) + )) { VALIDATOR_STATUS_ACTIVE - } else if (option::is_some(&find_validator(&validator_set.pending_inactive, pool_address))) { + } else if (option::is_some( + &find_validator(&validator_set.pending_inactive, pool_address) + )) { VALIDATOR_STATUS_PENDING_INACTIVE } else { VALIDATOR_STATUS_INACTIVE @@ -419,17 +426,20 @@ module supra_framework::stake { #[view] /// Return the voting power of the validator in the current epoch. /// This is the same as the validator's total active and pending_inactive stake. - public fun get_current_epoch_voting_power(pool_address: address): u64 acquires StakePool, ValidatorSet { + public fun get_current_epoch_voting_power( + pool_address: address + ): u64 acquires StakePool, ValidatorSet { assert_stake_pool_exists(pool_address); let validator_state = get_validator_state(pool_address); // Both active and pending inactive validators can still vote in the current epoch. - if (validator_state == VALIDATOR_STATUS_ACTIVE || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE) { - let active_stake = coin::value(&borrow_global(pool_address).active); - let pending_inactive_stake = coin::value(&borrow_global(pool_address).pending_inactive); + if (validator_state == VALIDATOR_STATUS_ACTIVE + || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE) { + let active_stake = + coin::value(&borrow_global(pool_address).active); + let pending_inactive_stake = + coin::value(&borrow_global(pool_address).pending_inactive); active_stake + pending_inactive_stake - } else { - 0 - } + } else { 0 } } #[view] @@ -460,10 +470,18 @@ module supra_framework::stake { #[view] /// Return the number of successful and failed proposals for the proposal at the given validator index. - public fun get_current_epoch_proposal_counts(validator_index: u64): (u64, u64) acquires ValidatorPerformance { - let validator_performances = &borrow_global(@supra_framework).validators; - let validator_performance = vector::borrow(validator_performances, validator_index); - (validator_performance.successful_proposals, validator_performance.failed_proposals) + public fun get_current_epoch_proposal_counts( + validator_index: u64 + ): (u64, u64) acquires ValidatorPerformance { + let validator_performances = + &borrow_global(@supra_framework).validators; + let validator_performance = vector::borrow( + validator_performances, validator_index + ); + ( + validator_performance.successful_proposals, + validator_performance.failed_proposals + ) } #[view] @@ -473,7 +491,11 @@ module supra_framework::stake { ): (vector, vector, vector) acquires ValidatorConfig { assert_stake_pool_exists(pool_address); let validator_config = borrow_global(pool_address); - (validator_config.consensus_pubkey, validator_config.network_addresses, validator_config.fullnode_addresses) + ( + validator_config.consensus_pubkey, + validator_config.network_addresses, + validator_config.fullnode_addresses + ) } #[view] @@ -485,31 +507,33 @@ module supra_framework::stake { public(friend) fun initialize(supra_framework: &signer) { system_addresses::assert_supra_framework(supra_framework); - move_to(supra_framework, ValidatorSet { - consensus_scheme: 0, - active_validators: vector::empty(), - pending_active: vector::empty(), - pending_inactive: vector::empty(), - total_voting_power: 0, - total_joining_power: 0, - }); + move_to( + supra_framework, + ValidatorSet { + consensus_scheme: 0, + active_validators: vector::empty(), + pending_active: vector::empty(), + pending_inactive: vector::empty(), + total_voting_power: 0, + total_joining_power: 0 + } + ); - move_to(supra_framework, ValidatorPerformance { - validators: vector::empty(), - }); + move_to(supra_framework, ValidatorPerformance { validators: vector::empty() }); } /// This is only called during Genesis, which is where MintCapability can be created. /// Beyond genesis, no one can create SupraCoin mint/burn capabilities. - public(friend) fun store_supra_coin_mint_cap(supra_framework: &signer, mint_cap: MintCapability) { + public(friend) fun store_supra_coin_mint_cap( + supra_framework: &signer, mint_cap: MintCapability + ) { system_addresses::assert_supra_framework(supra_framework); move_to(supra_framework, SupraCoinCapabilities { mint_cap }) } /// Allow on chain governance to remove validators from the validator set. public fun remove_validators( - supra_framework: &signer, - validators: &vector
, + supra_framework: &signer, validators: &vector
) acquires ValidatorSet { assert_reconfig_not_in_progress(); system_addresses::assert_supra_framework(supra_framework); @@ -530,14 +554,17 @@ module supra_framework::stake { invariant spec_validator_indices_are_valid(active_validators); invariant spec_validators_are_initialized(pending_inactive); invariant spec_validator_indices_are_valid(pending_inactive); - invariant ghost_active_num + ghost_pending_inactive_num == len(active_validators) + len(pending_inactive); + invariant ghost_active_num + ghost_pending_inactive_num + == len(active_validators) + len(pending_inactive); }; i < len_validators }) { let validator = *vector::borrow(validators, i); let validator_index = find_validator(active_validators, validator); if (option::is_some(&validator_index)) { - let validator_info = vector::swap_remove(active_validators, *option::borrow(&validator_index)); + let validator_info = vector::swap_remove( + active_validators, *option::borrow(&validator_index) + ); vector::push_back(pending_inactive, validator_info); spec { update ghost_active_num = ghost_active_num - 1; @@ -556,15 +583,18 @@ module supra_framework::stake { owner: &signer, initial_stake_amount: u64, operator: address, - voter: address, + voter: address ) acquires AllowedValidators, OwnerCapability, StakePool, ValidatorSet { initialize_owner(owner); - move_to(owner, ValidatorConfig { - consensus_pubkey: vector::empty(), - network_addresses: vector::empty(), - fullnode_addresses: vector::empty(), - validator_index: 0, - }); + move_to( + owner, + ValidatorConfig { + consensus_pubkey: vector::empty(), + network_addresses: vector::empty(), + fullnode_addresses: vector::empty(), + validator_index: 0 + } + ); if (initial_stake_amount > 0) { add_stake(owner, initial_stake_amount); @@ -584,50 +614,74 @@ module supra_framework::stake { account: &signer, consensus_pubkey: vector, network_addresses: vector, - fullnode_addresses: vector, + fullnode_addresses: vector ) acquires AllowedValidators { // Checks the public key is valid to prevent rogue-key attacks. - let valid_public_key = ed25519::new_validated_public_key_from_bytes(consensus_pubkey); - assert!(option::is_some(&valid_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY)); + let valid_public_key = + ed25519::new_validated_public_key_from_bytes(consensus_pubkey); + assert!( + option::is_some(&valid_public_key), + error::invalid_argument(EINVALID_PUBLIC_KEY) + ); initialize_owner(account); - move_to(account, ValidatorConfig { - consensus_pubkey, - network_addresses, - fullnode_addresses, - validator_index: 0, - }); + move_to( + account, + ValidatorConfig { + consensus_pubkey, + network_addresses, + fullnode_addresses, + validator_index: 0 + } + ); } fun initialize_owner(owner: &signer) acquires AllowedValidators { let owner_address = signer::address_of(owner); assert!(is_allowed(owner_address), error::not_found(EINELIGIBLE_VALIDATOR)); - assert!(!stake_pool_exists(owner_address), error::already_exists(EALREADY_REGISTERED)); - - move_to(owner, StakePool { - active: coin::zero(), - pending_active: coin::zero(), - pending_inactive: coin::zero(), - inactive: coin::zero(), - locked_until_secs: 0, - operator_address: owner_address, - delegated_voter: owner_address, - // Events. - initialize_validator_events: account::new_event_handle(owner), - set_operator_events: account::new_event_handle(owner), - add_stake_events: account::new_event_handle(owner), - reactivate_stake_events: account::new_event_handle(owner), - rotate_consensus_key_events: account::new_event_handle(owner), - update_network_and_fullnode_addresses_events: account::new_event_handle( - owner - ), - increase_lockup_events: account::new_event_handle(owner), - join_validator_set_events: account::new_event_handle(owner), - distribute_rewards_events: account::new_event_handle(owner), - unlock_stake_events: account::new_event_handle(owner), - withdraw_stake_events: account::new_event_handle(owner), - leave_validator_set_events: account::new_event_handle(owner), - }); + assert!( + !stake_pool_exists(owner_address), error::already_exists(EALREADY_REGISTERED) + ); + + move_to( + owner, + StakePool { + active: coin::zero(), + pending_active: coin::zero(), + pending_inactive: coin::zero(), + inactive: coin::zero(), + locked_until_secs: 0, + operator_address: owner_address, + delegated_voter: owner_address, + // Events. + initialize_validator_events: account::new_event_handle< + RegisterValidatorCandidateEvent>(owner), + set_operator_events: account::new_event_handle(owner), + add_stake_events: account::new_event_handle(owner), + reactivate_stake_events: account::new_event_handle( + owner + ), + rotate_consensus_key_events: account::new_event_handle< + RotateConsensusKeyEvent>(owner), + update_network_and_fullnode_addresses_events: account::new_event_handle< + UpdateNetworkAndFullnodeAddressesEvent>(owner), + increase_lockup_events: account::new_event_handle( + owner + ), + join_validator_set_events: account::new_event_handle( + owner + ), + distribute_rewards_events: account::new_event_handle( + owner + ), + unlock_stake_events: account::new_event_handle(owner), + withdraw_stake_events: account::new_event_handle( + owner + ), + leave_validator_set_events: account::new_event_handle< + LeaveValidatorSetEvent>(owner) + } + ); move_to(owner, OwnerCapability { pool_address: owner_address }); } @@ -641,8 +695,13 @@ module supra_framework::stake { /// Deposit `owner_cap` into `account`. This requires `account` to not already have ownership of another /// staking pool. - public fun deposit_owner_cap(owner: &signer, owner_cap: OwnerCapability) { - assert!(!exists(signer::address_of(owner)), error::not_found(EOWNER_CAP_ALREADY_EXISTS)); + public fun deposit_owner_cap( + owner: &signer, owner_cap: OwnerCapability + ) { + assert!( + !exists(signer::address_of(owner)), + error::not_found(EOWNER_CAP_ALREADY_EXISTS) + ); move_to(owner, owner_cap); } @@ -652,7 +711,9 @@ module supra_framework::stake { } /// Allows an owner to change the operator of the stake pool. - public entry fun set_operator(owner: &signer, new_operator: address) acquires OwnerCapability, StakePool { + public entry fun set_operator( + owner: &signer, new_operator: address + ) acquires OwnerCapability, StakePool { let owner_address = signer::address_of(owner); assert_owner_cap_exists(owner_address); let ownership_cap = borrow_global(owner_address); @@ -660,7 +721,9 @@ module supra_framework::stake { } /// Allows an account with ownership capability to change the operator of the stake pool. - public fun set_operator_with_cap(owner_cap: &OwnerCapability, new_operator: address) acquires StakePool { + public fun set_operator_with_cap( + owner_cap: &OwnerCapability, new_operator: address + ) acquires StakePool { let pool_address = owner_cap.pool_address; assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); @@ -669,26 +732,20 @@ module supra_framework::stake { if (std::features::module_event_migration_enabled()) { event::emit( - SetOperator { - pool_address, - old_operator, - new_operator, - }, + SetOperator { pool_address, old_operator, new_operator } ); }; event::emit_event( &mut stake_pool.set_operator_events, - SetOperatorEvent { - pool_address, - old_operator, - new_operator, - }, + SetOperatorEvent { pool_address, old_operator, new_operator } ); } /// Allows an owner to change the delegated voter of the stake pool. - public entry fun set_delegated_voter(owner: &signer, new_voter: address) acquires OwnerCapability, StakePool { + public entry fun set_delegated_voter( + owner: &signer, new_voter: address + ) acquires OwnerCapability, StakePool { let owner_address = signer::address_of(owner); assert_owner_cap_exists(owner_address); let ownership_cap = borrow_global(owner_address); @@ -696,7 +753,9 @@ module supra_framework::stake { } /// Allows an owner to change the delegated voter of the stake pool. - public fun set_delegated_voter_with_cap(owner_cap: &OwnerCapability, new_voter: address) acquires StakePool { + public fun set_delegated_voter_with_cap( + owner_cap: &OwnerCapability, new_voter: address + ) acquires StakePool { let pool_address = owner_cap.pool_address; assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); @@ -704,7 +763,9 @@ module supra_framework::stake { } /// Add `amount` of coins from the `account` owning the StakePool. - public entry fun add_stake(owner: &signer, amount: u64) acquires OwnerCapability, StakePool, ValidatorSet { + public entry fun add_stake( + owner: &signer, amount: u64 + ) acquires OwnerCapability, StakePool, ValidatorSet { let owner_address = signer::address_of(owner); assert_owner_cap_exists(owner_address); let ownership_cap = borrow_global(owner_address); @@ -712,7 +773,9 @@ module supra_framework::stake { } /// Add `coins` into `pool_address`. this requires the corresponding `owner_cap` to be passed in. - public fun add_stake_with_cap(owner_cap: &OwnerCapability, coins: Coin) acquires StakePool, ValidatorSet { + public fun add_stake_with_cap( + owner_cap: &OwnerCapability, coins: Coin + ) acquires StakePool, ValidatorSet { assert_reconfig_not_in_progress(); let pool_address = owner_cap.pool_address; assert_stake_pool_exists(pool_address); @@ -728,8 +791,9 @@ module supra_framework::stake { // Inactive validator's total stake will be tracked when they join the validator set. let validator_set = borrow_global_mut(@supra_framework); // Search directly rather using get_validator_state to save on unnecessary loops. - if (option::is_some(&find_validator(&validator_set.active_validators, pool_address)) || - option::is_some(&find_validator(&validator_set.pending_active, pool_address))) { + if (option::is_some( + &find_validator(&validator_set.active_validators, pool_address) + ) || option::is_some(&find_validator(&validator_set.pending_active, pool_address))) { update_voting_power_increase(amount); }; @@ -742,24 +806,21 @@ module supra_framework::stake { coin::merge(&mut stake_pool.active, coins); }; - let (_, maximum_stake) = staking_config::get_required_stake(&staking_config::get()); + let (_, maximum_stake) = + staking_config::get_required_stake(&staking_config::get()); let voting_power = get_next_epoch_voting_power(stake_pool); - assert!(voting_power <= maximum_stake, error::invalid_argument(ESTAKE_EXCEEDS_MAX)); + assert!( + voting_power <= maximum_stake, error::invalid_argument(ESTAKE_EXCEEDS_MAX) + ); if (std::features::module_event_migration_enabled()) { event::emit( - AddStake { - pool_address, - amount_added: amount, - }, + AddStake { pool_address, amount_added: amount } ); }; event::emit_event( &mut stake_pool.add_stake_events, - AddStakeEvent { - pool_address, - amount_added: amount, - }, + AddStakeEvent { pool_address, amount_added: amount } ); } @@ -772,7 +833,9 @@ module supra_framework::stake { reactivate_stake_with_cap(ownership_cap, amount); } - public fun reactivate_stake_with_cap(owner_cap: &OwnerCapability, amount: u64) acquires StakePool { + public fun reactivate_stake_with_cap( + owner_cap: &OwnerCapability, amount: u64 + ) acquires StakePool { assert_reconfig_not_in_progress(); let pool_address = owner_cap.pool_address; assert_stake_pool_exists(pool_address); @@ -790,18 +853,12 @@ module supra_framework::stake { if (std::features::module_event_migration_enabled()) { event::emit( - ReactivateStake { - pool_address, - amount, - }, + ReactivateStake { pool_address, amount } ); }; event::emit_event( &mut stake_pool.reactivate_stake_events, - ReactivateStakeEvent { - pool_address, - amount, - }, + ReactivateStakeEvent { pool_address, amount } ); } @@ -809,24 +866,37 @@ module supra_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, - genesis: bool, + genesis: bool ) acquires StakePool, ValidatorConfig { assert_reconfig_not_in_progress(); assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); - assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR)); + assert!( + signer::address_of(operator) == stake_pool.operator_address, + error::unauthenticated(ENOT_OPERATOR) + ); - assert!(exists(pool_address), error::not_found(EVALIDATOR_CONFIG)); + assert!( + exists(pool_address), error::not_found(EVALIDATOR_CONFIG) + ); let validator_info = borrow_global_mut(pool_address); let old_consensus_pubkey = validator_info.consensus_pubkey; // Checks the public key is valid to prevent rogue-key attacks. if (!genesis) { - let validated_public_key = ed25519::new_validated_public_key_from_bytes(new_consensus_pubkey); - assert!(option::is_some(&validated_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY)); + let validated_public_key = + ed25519::new_validated_public_key_from_bytes(new_consensus_pubkey); + assert!( + option::is_some(&validated_public_key), + error::invalid_argument(EINVALID_PUBLIC_KEY) + ); } else { - let validated_public_key = ed25519::new_validated_public_key_from_bytes(new_consensus_pubkey); - assert!(option::is_some(&validated_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY)); + let validated_public_key = + ed25519::new_validated_public_key_from_bytes(new_consensus_pubkey); + assert!( + option::is_some(&validated_public_key), + error::invalid_argument(EINVALID_PUBLIC_KEY) + ); }; validator_info.consensus_pubkey = new_consensus_pubkey; @@ -835,8 +905,8 @@ module supra_framework::stake { RotateConsensusKey { pool_address, old_consensus_pubkey, - new_consensus_pubkey, - }, + new_consensus_pubkey + } ); }; event::emit_event( @@ -844,8 +914,8 @@ module supra_framework::stake { RotateConsensusKeyEvent { pool_address, old_consensus_pubkey, - new_consensus_pubkey, - }, + new_consensus_pubkey + } ); } @@ -855,7 +925,7 @@ module supra_framework::stake { public(friend) fun rotate_consensus_key_genesis( operator: &signer, pool_address: address, - new_consensus_pubkey: vector, + new_consensus_pubkey: vector ) acquires StakePool, ValidatorConfig { rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, true); } @@ -864,7 +934,7 @@ module supra_framework::stake { public entry fun rotate_consensus_key( operator: &signer, pool_address: address, - new_consensus_pubkey: vector, + new_consensus_pubkey: vector ) acquires StakePool, ValidatorConfig { rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, false); } @@ -874,13 +944,18 @@ module supra_framework::stake { operator: &signer, pool_address: address, new_network_addresses: vector, - new_fullnode_addresses: vector, + new_fullnode_addresses: vector ) acquires StakePool, ValidatorConfig { assert_reconfig_not_in_progress(); assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); - assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR)); - assert!(exists(pool_address), error::not_found(EVALIDATOR_CONFIG)); + assert!( + signer::address_of(operator) == stake_pool.operator_address, + error::unauthenticated(ENOT_OPERATOR) + ); + assert!( + exists(pool_address), error::not_found(EVALIDATOR_CONFIG) + ); let validator_info = borrow_global_mut(pool_address); let old_network_addresses = validator_info.network_addresses; validator_info.network_addresses = new_network_addresses; @@ -894,8 +969,8 @@ module supra_framework::stake { old_network_addresses, new_network_addresses, old_fullnode_addresses, - new_fullnode_addresses, - }, + new_fullnode_addresses + } ); }; event::emit_event( @@ -905,8 +980,8 @@ module supra_framework::stake { old_network_addresses, new_network_addresses, old_fullnode_addresses, - new_fullnode_addresses, - }, + new_fullnode_addresses + } ); } @@ -928,8 +1003,13 @@ module supra_framework::stake { let stake_pool = borrow_global_mut(pool_address); let old_locked_until_secs = stake_pool.locked_until_secs; - let new_locked_until_secs = timestamp::now_seconds() + staking_config::get_recurring_lockup_duration(&config); - assert!(old_locked_until_secs < new_locked_until_secs, error::invalid_argument(EINVALID_LOCKUP)); + let new_locked_until_secs = + timestamp::now_seconds() + + staking_config::get_recurring_lockup_duration(&config); + assert!( + old_locked_until_secs < new_locked_until_secs, + error::invalid_argument(EINVALID_LOCKUP) + ); stake_pool.locked_until_secs = new_locked_until_secs; if (std::features::module_event_migration_enabled()) { @@ -937,8 +1017,8 @@ module supra_framework::stake { IncreaseLockup { pool_address, old_locked_until_secs, - new_locked_until_secs, - }, + new_locked_until_secs + } ); }; event::emit_event( @@ -946,19 +1026,18 @@ module supra_framework::stake { IncreaseLockupEvent { pool_address, old_locked_until_secs, - new_locked_until_secs, - }, + new_locked_until_secs + } ); } /// This can only called by the operator of the validator/staking pool. public entry fun join_validator_set( - operator: &signer, - pool_address: address + operator: &signer, pool_address: address ) acquires StakePool, ValidatorConfig, ValidatorSet { assert!( staking_config::get_allow_validator_set_change(&staking_config::get()), - error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED), + error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED) ); join_validator_set_internal(operator, pool_address); @@ -971,16 +1050,18 @@ module supra_framework::stake { /// /// This internal version can only be called by the Genesis module during Genesis. public(friend) fun join_validator_set_internal( - operator: &signer, - pool_address: address + operator: &signer, pool_address: address ) acquires StakePool, ValidatorConfig, ValidatorSet { assert_reconfig_not_in_progress(); assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); - assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR)); + assert!( + signer::address_of(operator) == stake_pool.operator_address, + error::unauthenticated(ENOT_OPERATOR) + ); assert!( get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE, - error::invalid_state(EALREADY_ACTIVE_VALIDATOR), + error::invalid_state(EALREADY_ACTIVE_VALIDATOR) ); let config = staking_config::get(); @@ -994,7 +1075,10 @@ module supra_framework::stake { // Add validator to pending_active, to be activated in the next epoch. let validator_config = borrow_global_mut(pool_address); - assert!(!vector::is_empty(&validator_config.consensus_pubkey), error::invalid_argument(EINVALID_PUBLIC_KEY)); + assert!( + !vector::is_empty(&validator_config.consensus_pubkey), + error::invalid_argument(EINVALID_PUBLIC_KEY) + ); // Validate the current validator set size has not exceeded the limit. let validator_set = borrow_global_mut(@supra_framework); @@ -1002,17 +1086,19 @@ module supra_framework::stake { &mut validator_set.pending_active, generate_validator_info(pool_address, stake_pool, *validator_config) ); - let validator_set_size = vector::length(&validator_set.active_validators) + vector::length( - &validator_set.pending_active + let validator_set_size = vector::length(&validator_set.active_validators) + + vector::length(&validator_set.pending_active); + assert!( + validator_set_size <= MAX_VALIDATOR_SET_SIZE, + error::invalid_argument(EVALIDATOR_SET_TOO_LARGE) ); - assert!(validator_set_size <= MAX_VALIDATOR_SET_SIZE, error::invalid_argument(EVALIDATOR_SET_TOO_LARGE)); if (std::features::module_event_migration_enabled()) { event::emit(JoinValidatorSet { pool_address }); }; event::emit_event( &mut stake_pool.join_validator_set_events, - JoinValidatorSetEvent { pool_address }, + JoinValidatorSetEvent { pool_address } ); } @@ -1029,9 +1115,7 @@ module supra_framework::stake { public fun unlock_with_cap(amount: u64, owner_cap: &OwnerCapability) acquires StakePool { assert_reconfig_not_in_progress(); // Short-circuit if amount to unlock is 0 so we don't emit events. - if (amount == 0) { - return - }; + if (amount == 0) { return }; // Unlocked coins are moved to pending_inactive. When the current lockup cycle expires, they will be moved into // inactive in the earliest possible epoch transition. @@ -1045,25 +1129,18 @@ module supra_framework::stake { if (std::features::module_event_migration_enabled()) { event::emit( - UnlockStake { - pool_address, - amount_unlocked: amount, - }, + UnlockStake { pool_address, amount_unlocked: amount } ); }; event::emit_event( &mut stake_pool.unlock_stake_events, - UnlockStakeEvent { - pool_address, - amount_unlocked: amount, - }, + UnlockStakeEvent { pool_address, amount_unlocked: amount } ); } /// Withdraw from `account`'s inactive stake. public entry fun withdraw( - owner: &signer, - withdraw_amount: u64 + owner: &signer, withdraw_amount: u64 ) acquires OwnerCapability, StakePool, ValidatorSet { let owner_address = signer::address_of(owner); assert_owner_cap_exists(owner_address); @@ -1074,8 +1151,7 @@ module supra_framework::stake { /// Withdraw from `pool_address`'s inactive stake with the corresponding `owner_cap`. public fun withdraw_with_cap( - owner_cap: &OwnerCapability, - withdraw_amount: u64 + owner_cap: &OwnerCapability, withdraw_amount: u64 ): Coin acquires StakePool, ValidatorSet { assert_reconfig_not_in_progress(); let pool_address = owner_cap.pool_address; @@ -1084,9 +1160,10 @@ module supra_framework::stake { // There's an edge case where a validator unlocks their stake and leaves the validator set before // the stake is fully unlocked (the current lockup cycle has not expired yet). // This can leave their stake stuck in pending_inactive even after the current lockup cycle expires. - if (get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE && - timestamp::now_seconds() >= stake_pool.locked_until_secs) { - let pending_inactive_stake = coin::extract_all(&mut stake_pool.pending_inactive); + if (get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE + && timestamp::now_seconds() >= stake_pool.locked_until_secs) { + let pending_inactive_stake = + coin::extract_all(&mut stake_pool.pending_inactive); coin::merge(&mut stake_pool.inactive, pending_inactive_stake); }; @@ -1096,18 +1173,12 @@ module supra_framework::stake { if (std::features::module_event_migration_enabled()) { event::emit( - WithdrawStake { - pool_address, - amount_withdrawn: withdraw_amount, - }, + WithdrawStake { pool_address, amount_withdrawn: withdraw_amount } ); }; event::emit_event( &mut stake_pool.withdraw_stake_events, - WithdrawStakeEvent { - pool_address, - amount_withdrawn: withdraw_amount, - }, + WithdrawStakeEvent { pool_address, amount_withdrawn: withdraw_amount } ); coin::extract(&mut stake_pool.inactive, withdraw_amount) @@ -1120,27 +1191,32 @@ module supra_framework::stake { /// /// Can only be called by the operator of the validator/staking pool. public entry fun leave_validator_set( - operator: &signer, - pool_address: address + operator: &signer, pool_address: address ) acquires StakePool, ValidatorSet { assert_reconfig_not_in_progress(); let config = staking_config::get(); assert!( staking_config::get_allow_validator_set_change(&config), - error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED), + error::invalid_argument(ENO_POST_GENESIS_VALIDATOR_SET_CHANGE_ALLOWED) ); assert_stake_pool_exists(pool_address); let stake_pool = borrow_global_mut(pool_address); // Account has to be the operator. - assert!(signer::address_of(operator) == stake_pool.operator_address, error::unauthenticated(ENOT_OPERATOR)); + assert!( + signer::address_of(operator) == stake_pool.operator_address, + error::unauthenticated(ENOT_OPERATOR) + ); let validator_set = borrow_global_mut(@supra_framework); // If the validator is still pending_active, directly kick the validator out. - let maybe_pending_active_index = find_validator(&validator_set.pending_active, pool_address); + let maybe_pending_active_index = + find_validator(&validator_set.pending_active, pool_address); if (option::is_some(&maybe_pending_active_index)) { vector::swap_remove( - &mut validator_set.pending_active, option::extract(&mut maybe_pending_active_index)); + &mut validator_set.pending_active, + option::extract(&mut maybe_pending_active_index) + ); // Decrease the voting power increase as the pending validator's voting power was added when they requested // to join. Now that they changed their mind, their voting power should not affect the joining limit of this @@ -1150,17 +1226,26 @@ module supra_framework::stake { // rounding error somewhere that can lead to an underflow, we still want to allow this transaction to // succeed. if (validator_set.total_joining_power > validator_stake) { - validator_set.total_joining_power = validator_set.total_joining_power - validator_stake; + validator_set.total_joining_power = validator_set.total_joining_power + - validator_stake; } else { validator_set.total_joining_power = 0; }; } else { // Validate that the validator is already part of the validator set. - let maybe_active_index = find_validator(&validator_set.active_validators, pool_address); - assert!(option::is_some(&maybe_active_index), error::invalid_state(ENOT_VALIDATOR)); + let maybe_active_index = + find_validator(&validator_set.active_validators, pool_address); + assert!( + option::is_some(&maybe_active_index), error::invalid_state(ENOT_VALIDATOR) + ); let validator_info = vector::swap_remove( - &mut validator_set.active_validators, option::extract(&mut maybe_active_index)); - assert!(vector::length(&validator_set.active_validators) > 0, error::invalid_state(ELAST_VALIDATOR)); + &mut validator_set.active_validators, + option::extract(&mut maybe_active_index) + ); + assert!( + vector::length(&validator_set.active_validators) > 0, + error::invalid_state(ELAST_VALIDATOR) + ); vector::push_back(&mut validator_set.pending_inactive, validator_info); if (std::features::module_event_migration_enabled()) { @@ -1168,9 +1253,7 @@ module supra_framework::stake { }; event::emit_event( &mut stake_pool.leave_validator_set_events, - LeaveValidatorSetEvent { - pool_address, - }, + LeaveValidatorSetEvent { pool_address } ); }; } @@ -1181,14 +1264,14 @@ module supra_framework::stake { public fun is_current_epoch_validator(pool_address: address): bool acquires ValidatorSet { assert_stake_pool_exists(pool_address); let validator_state = get_validator_state(pool_address); - validator_state == VALIDATOR_STATUS_ACTIVE || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE + validator_state == VALIDATOR_STATUS_ACTIVE + || validator_state == VALIDATOR_STATUS_PENDING_INACTIVE } /// Update the validator performance (proposal statistics). This is only called by block::prologue(). /// This function cannot abort. public(friend) fun update_performance_statistics( - proposer_index: Option, - failed_proposer_indices: vector + proposer_index: Option, failed_proposer_indices: vector ) acquires ValidatorPerformance { // Validator set cannot change until the end of the epoch, so the validator index in arguments should // match with those of the validators in ValidatorPerformance resource. @@ -1205,7 +1288,9 @@ module supra_framework::stake { // Here, and in all other vector::borrow, skip any validator indices that are out of bounds, // this ensures that this function doesn't abort if there are out of bounds errors. if (cur_proposer_index < validator_len) { - let validator = vector::borrow_mut(&mut validator_perf.validators, cur_proposer_index); + let validator = vector::borrow_mut( + &mut validator_perf.validators, cur_proposer_index + ); spec { assume validator.successful_proposals + 1 <= MAX_U64; }; @@ -1218,17 +1303,25 @@ module supra_framework::stake { while ({ spec { invariant len(validator_perf.validators) == validator_len; - invariant (option::spec_is_some(ghost_proposer_idx) && option::spec_borrow( - ghost_proposer_idx - ) < validator_len) ==> - (validator_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals == - ghost_valid_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals + 1); + invariant ( + option::spec_is_some(ghost_proposer_idx) + && option::spec_borrow(ghost_proposer_idx) < validator_len + ) ==> + ( + validator_perf.validators[option::spec_borrow(ghost_proposer_idx)] + .successful_proposals + == ghost_valid_perf.validators[option::spec_borrow( + ghost_proposer_idx + )].successful_proposals + 1 + ); }; f < f_len }) { let validator_index = *vector::borrow(&failed_proposer_indices, f); if (validator_index < validator_len) { - let validator = vector::borrow_mut(&mut validator_perf.validators, validator_index); + let validator = vector::borrow_mut( + &mut validator_perf.validators, validator_index + ); spec { assume validator.failed_proposals + 1 <= MAX_U64; }; @@ -1248,24 +1341,29 @@ module supra_framework::stake { /// pending inactive validators so they no longer can vote. /// 4. The validator's voting power in the validator set is updated to be the corresponding staking pool's voting /// power. - public(friend) fun on_new_epoch( - ) acquires StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { + public(friend) fun on_new_epoch() acquires StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { let validator_set = borrow_global_mut(@supra_framework); let config = staking_config::get(); let validator_perf = borrow_global_mut(@supra_framework); // Process pending stake and distribute transaction fees and rewards for each currently active validator. - vector::for_each_ref(&validator_set.active_validators, |validator| { - let validator: &ValidatorInfo = validator; - update_stake_pool(validator_perf, validator.addr, &config); - }); + vector::for_each_ref( + &validator_set.active_validators, + |validator| { + let validator: &ValidatorInfo = validator; + update_stake_pool(validator_perf, validator.addr, &config); + } + ); // Process pending stake and distribute transaction fees and rewards for each currently pending_inactive validator // (requested to leave but not removed yet). - vector::for_each_ref(&validator_set.pending_inactive, |validator| { - let validator: &ValidatorInfo = validator; - update_stake_pool(validator_perf, validator.addr, &config); - }); + vector::for_each_ref( + &validator_set.pending_inactive, + |validator| { + let validator: &ValidatorInfo = validator; + update_stake_pool(validator_perf, validator.addr, &config); + } + ); // Activate currently pending_active validators. append(&mut validator_set.active_validators, &mut validator_set.pending_active); @@ -1288,18 +1386,23 @@ module supra_framework::stake { }; i < vlen }) { - let old_validator_info = vector::borrow_mut(&mut validator_set.active_validators, i); + let old_validator_info = vector::borrow_mut( + &mut validator_set.active_validators, i + ); let pool_address = old_validator_info.addr; let validator_config = borrow_global_mut(pool_address); let stake_pool = borrow_global_mut(pool_address); - let new_validator_info = generate_validator_info(pool_address, stake_pool, *validator_config); + let new_validator_info = + generate_validator_info(pool_address, stake_pool, *validator_config); // A validator needs at least the min stake required to join the validator set. if (new_validator_info.voting_power >= minimum_stake) { spec { - assume total_voting_power + new_validator_info.voting_power <= MAX_U128; + assume total_voting_power + new_validator_info.voting_power + <= MAX_U128; }; - total_voting_power = total_voting_power + (new_validator_info.voting_power as u128); + total_voting_power = total_voting_power + + (new_validator_info.voting_power as u128); vector::push_back(&mut next_epoch_validators, new_validator_info); }; i = i + 1; @@ -1311,7 +1414,8 @@ module supra_framework::stake { // Update validator indices, reset performance scores, and renew lockups. validator_perf.validators = vector::empty(); - let recurring_lockup_duration_secs = staking_config::get_recurring_lockup_duration(&config); + let recurring_lockup_duration_secs = + staking_config::get_recurring_lockup_duration(&config); let vlen = vector::length(&validator_set.active_validators); let validator_index = 0; while ({ @@ -1322,37 +1426,47 @@ module supra_framework::stake { invariant 0 <= validator_index && validator_index <= vlen; invariant vlen == len(validator_set.active_validators); invariant forall i in 0..validator_index: - global(validator_set.active_validators[i].addr).validator_index < validator_index; + global(validator_set.active_validators[i].addr).validator_index + < validator_index; invariant forall i in 0..validator_index: - validator_set.active_validators[i].config.validator_index < validator_index; + validator_set.active_validators[i].config.validator_index + < validator_index; invariant len(validator_perf.validators) == validator_index; }; validator_index < vlen }) { - let validator_info = vector::borrow_mut(&mut validator_set.active_validators, validator_index); + let validator_info = vector::borrow_mut( + &mut validator_set.active_validators, validator_index + ); validator_info.config.validator_index = validator_index; - let validator_config = borrow_global_mut(validator_info.addr); + let validator_config = + borrow_global_mut(validator_info.addr); validator_config.validator_index = validator_index; - vector::push_back(&mut validator_perf.validators, IndividualValidatorPerformance { - successful_proposals: 0, - failed_proposals: 0, - }); + vector::push_back( + &mut validator_perf.validators, + IndividualValidatorPerformance { + successful_proposals: 0, + failed_proposals: 0 + } + ); // Automatically renew a validator's lockup for validators that will still be in the validator set in the // next epoch. let stake_pool = borrow_global_mut(validator_info.addr); let now_secs = timestamp::now_seconds(); - let reconfig_start_secs = if (chain_status::is_operating()) { - get_reconfig_start_time_secs() - } else { - now_secs - }; + let reconfig_start_secs = + if (chain_status::is_operating()) { + get_reconfig_start_time_secs() + } else { + now_secs + }; if (stake_pool.locked_until_secs <= reconfig_start_secs) { spec { assume now_secs + recurring_lockup_duration_secs <= MAX_U64; }; - stake_pool.locked_until_secs = now_secs + recurring_lockup_duration_secs; + stake_pool.locked_until_secs = now_secs + + recurring_lockup_duration_secs; }; validator_index = validator_index + 1; @@ -1370,14 +1484,14 @@ module supra_framework::stake { validator_consensus_infos_from_validator_set(validator_set) } - public fun next_validator_consensus_infos(): vector acquires ValidatorSet, ValidatorPerformance, StakePool, ValidatorFees, ValidatorConfig { // Init. let cur_validator_set = borrow_global(@supra_framework); let staking_config = staking_config::get(); let validator_perf = borrow_global(@supra_framework); let (minimum_stake, _) = staking_config::get_required_stake(&staking_config); - let (rewards_rate, rewards_rate_denominator) = staking_config::get_reward_rate(&staking_config); + let (rewards_rate, rewards_rate_denominator) = + staking_config::get_reward_rate(&staking_config); // Compute new validator set. let new_active_validators = vector[]; @@ -1403,48 +1517,66 @@ module supra_framework::stake { candidate_idx < num_candidates }) { let candidate_in_current_validator_set = candidate_idx < num_cur_actives; - let candidate = if (candidate_idx < num_cur_actives) { - vector::borrow(&cur_validator_set.active_validators, candidate_idx) - } else { - vector::borrow(&cur_validator_set.pending_active, candidate_idx - num_cur_actives) - }; + let candidate = + if (candidate_idx < num_cur_actives) { + vector::borrow(&cur_validator_set.active_validators, candidate_idx) + } else { + vector::borrow( + &cur_validator_set.pending_active, candidate_idx + - num_cur_actives + ) + }; let stake_pool = borrow_global(candidate.addr); let cur_active = coin::value(&stake_pool.active); let cur_pending_active = coin::value(&stake_pool.pending_active); let cur_pending_inactive = coin::value(&stake_pool.pending_inactive); - let cur_reward = if (candidate_in_current_validator_set && cur_active > 0) { - spec { - assert candidate.config.validator_index < len(validator_perf.validators); - }; - let cur_perf = vector::borrow(&validator_perf.validators, candidate.config.validator_index); - spec { - assume cur_perf.successful_proposals + cur_perf.failed_proposals <= MAX_U64; - }; - calculate_rewards_amount(cur_active, cur_perf.successful_proposals, cur_perf.successful_proposals + cur_perf.failed_proposals, rewards_rate, rewards_rate_denominator) - } else { - 0 - }; + let cur_reward = + if (candidate_in_current_validator_set && cur_active > 0) { + spec { + assert candidate.config.validator_index + < len(validator_perf.validators); + }; + let cur_perf = vector::borrow( + &validator_perf.validators, candidate.config.validator_index + ); + spec { + assume cur_perf.successful_proposals + + cur_perf.failed_proposals <= MAX_U64; + }; + calculate_rewards_amount( + cur_active, + cur_perf.successful_proposals, + cur_perf.successful_proposals + cur_perf.failed_proposals, + rewards_rate, + rewards_rate_denominator + ) + } else { 0 }; let cur_fee = 0; if (features::collect_and_distribute_gas_fees()) { - let fees_table = &borrow_global(@supra_framework).fees_table; + let fees_table = + &borrow_global(@supra_framework).fees_table; if (table::contains(fees_table, candidate.addr)) { let fee_coin = table::borrow(fees_table, candidate.addr); cur_fee = coin::value(fee_coin); } }; - let lockup_expired = get_reconfig_start_time_secs() >= stake_pool.locked_until_secs; + let lockup_expired = + get_reconfig_start_time_secs() >= stake_pool.locked_until_secs; spec { - assume cur_active + cur_pending_active + cur_reward + cur_fee <= MAX_U64; - assume cur_active + cur_pending_inactive + cur_pending_active + cur_reward + cur_fee <= MAX_U64; + assume cur_active + cur_pending_active + cur_reward + cur_fee + <= MAX_U64; + assume cur_active + cur_pending_inactive + cur_pending_active + + cur_reward + cur_fee <= MAX_U64; }; let new_voting_power = cur_active - + if (lockup_expired) { 0 } else { cur_pending_inactive } - + cur_pending_active - + cur_reward + cur_fee; + + if (lockup_expired) { 0 } + else { + cur_pending_inactive + } + cur_pending_active + cur_reward + cur_fee; if (new_voting_power >= minimum_stake) { let config = *borrow_global(candidate.addr); @@ -1452,7 +1584,7 @@ module supra_framework::stake { let new_validator_info = ValidatorInfo { addr: candidate.addr, voting_power: new_voting_power, - config, + config }; // Update ValidatorSet. @@ -1473,13 +1605,15 @@ module supra_framework::stake { pending_inactive: vector[], pending_active: vector[], total_voting_power: new_total_power, - total_joining_power: 0, + total_joining_power: 0 }; validator_consensus_infos_from_validator_set(&new_validator_set) } - fun validator_consensus_infos_from_validator_set(validator_set: &ValidatorSet): vector { + fun validator_consensus_infos_from_validator_set( + validator_set: &ValidatorSet + ): vector { let validator_consensus_infos = vector[]; let num_active = vector::length(&validator_set.active_validators); @@ -1493,63 +1627,95 @@ module supra_framework::stake { let idx = 0; while ({ spec { - invariant idx <= len(validator_set.active_validators) + len(validator_set.pending_inactive); + invariant idx + <= len(validator_set.active_validators) + + len(validator_set.pending_inactive); invariant len(validator_consensus_infos) == idx; - invariant len(validator_consensus_infos) <= len(validator_set.active_validators) + len(validator_set.pending_inactive); + invariant len(validator_consensus_infos) + <= len(validator_set.active_validators) + + len(validator_set.pending_inactive); }; idx < total }) { - vector::push_back(&mut validator_consensus_infos, validator_consensus_info::default()); + vector::push_back( + &mut validator_consensus_infos, validator_consensus_info::default() + ); idx = idx + 1; }; spec { - assert len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive); - assert spec_validator_indices_are_valid_config(validator_set.active_validators, - len(validator_set.active_validators) + len(validator_set.pending_inactive)); + assert len(validator_consensus_infos) + == len(validator_set.active_validators) + + len(validator_set.pending_inactive); + assert spec_validator_indices_are_valid_config( + validator_set.active_validators, + len(validator_set.active_validators) + + len(validator_set.pending_inactive) + ); }; - vector::for_each_ref(&validator_set.active_validators, |obj| { - let vi: &ValidatorInfo = obj; - spec { - assume len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive); - assert vi.config.validator_index < len(validator_consensus_infos); - }; - let vci = vector::borrow_mut(&mut validator_consensus_infos, vi.config.validator_index); - *vci = validator_consensus_info::new( - vi.addr, - vi.config.consensus_pubkey, - vi.voting_power - ); - spec { - assert len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive); - }; - }); + vector::for_each_ref( + &validator_set.active_validators, + |obj| { + let vi: &ValidatorInfo = obj; + spec { + assume len(validator_consensus_infos) + == len(validator_set.active_validators) + + len(validator_set.pending_inactive); + assert vi.config.validator_index < len(validator_consensus_infos); + }; + let vci = vector::borrow_mut( + &mut validator_consensus_infos, vi.config.validator_index + ); + *vci = validator_consensus_info::new( + vi.addr, + vi.config.consensus_pubkey, + vi.voting_power + ); + spec { + assert len(validator_consensus_infos) + == len(validator_set.active_validators) + + len(validator_set.pending_inactive); + }; + } + ); - vector::for_each_ref(&validator_set.pending_inactive, |obj| { - let vi: &ValidatorInfo = obj; - spec { - assume len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive); - assert vi.config.validator_index < len(validator_consensus_infos); - }; - let vci = vector::borrow_mut(&mut validator_consensus_infos, vi.config.validator_index); - *vci = validator_consensus_info::new( - vi.addr, - vi.config.consensus_pubkey, - vi.voting_power - ); - spec { - assert len(validator_consensus_infos) == len(validator_set.active_validators) + len(validator_set.pending_inactive); - }; - }); + vector::for_each_ref( + &validator_set.pending_inactive, + |obj| { + let vi: &ValidatorInfo = obj; + spec { + assume len(validator_consensus_infos) + == len(validator_set.active_validators) + + len(validator_set.pending_inactive); + assert vi.config.validator_index < len(validator_consensus_infos); + }; + let vci = vector::borrow_mut( + &mut validator_consensus_infos, vi.config.validator_index + ); + *vci = validator_consensus_info::new( + vi.addr, + vi.config.consensus_pubkey, + vi.voting_power + ); + spec { + assert len(validator_consensus_infos) + == len(validator_set.active_validators) + + len(validator_set.pending_inactive); + }; + } + ); validator_consensus_infos } fun addresses_from_validator_infos(infos: &vector): vector
{ - vector::map_ref(infos, |obj| { - let info: &ValidatorInfo = obj; - info.addr - }) + vector::map_ref( + infos, + |obj| { + let info: &ValidatorInfo = obj; + info.addr + } + ) } /// Calculate the stake amount of a stake pool for the next epoch. @@ -1562,43 +1728,54 @@ module supra_framework::stake { fun update_stake_pool( validator_perf: &ValidatorPerformance, pool_address: address, - staking_config: &StakingConfig, + staking_config: &StakingConfig ) acquires StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorFees { let stake_pool = borrow_global_mut(pool_address); let validator_config = borrow_global(pool_address); - let cur_validator_perf = vector::borrow(&validator_perf.validators, validator_config.validator_index); + let cur_validator_perf = vector::borrow( + &validator_perf.validators, validator_config.validator_index + ); let num_successful_proposals = cur_validator_perf.successful_proposals; spec { // The following addition should not overflow because `num_total_proposals` cannot be larger than 86400, // the maximum number of proposals in a day (1 proposal per second). - assume cur_validator_perf.successful_proposals + cur_validator_perf.failed_proposals <= MAX_U64; + assume cur_validator_perf.successful_proposals + + cur_validator_perf.failed_proposals <= MAX_U64; }; - let num_total_proposals = cur_validator_perf.successful_proposals + cur_validator_perf.failed_proposals; - let (rewards_rate, rewards_rate_denominator) = staking_config::get_reward_rate(staking_config); - let rewards_active = distribute_rewards( - &mut stake_pool.active, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ); - let rewards_pending_inactive = distribute_rewards( - &mut stake_pool.pending_inactive, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ); + let num_total_proposals = + cur_validator_perf.successful_proposals + + cur_validator_perf.failed_proposals; + let (rewards_rate, rewards_rate_denominator) = + staking_config::get_reward_rate(staking_config); + let rewards_active = + distribute_rewards( + &mut stake_pool.active, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); + let rewards_pending_inactive = + distribute_rewards( + &mut stake_pool.pending_inactive, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); spec { assume rewards_active + rewards_pending_inactive <= MAX_U64; }; let rewards_amount = rewards_active + rewards_pending_inactive; // Pending active stake can now be active. - coin::merge(&mut stake_pool.active, coin::extract_all(&mut stake_pool.pending_active)); + coin::merge( + &mut stake_pool.active, coin::extract_all(&mut stake_pool.pending_active) + ); // Additionally, distribute transaction fees. if (features::collect_and_distribute_gas_fees()) { - let fees_table = &mut borrow_global_mut(@supra_framework).fees_table; + let fees_table = + &mut borrow_global_mut(@supra_framework).fees_table; if (table::contains(fees_table, pool_address)) { let coin = table::remove(fees_table, pool_address); coin::merge(&mut stake_pool.active, coin); @@ -1610,7 +1787,7 @@ module supra_framework::stake { if (get_reconfig_start_time_secs() >= current_lockup_expiration) { coin::merge( &mut stake_pool.inactive, - coin::extract_all(&mut stake_pool.pending_inactive), + coin::extract_all(&mut stake_pool.pending_inactive) ); }; @@ -1619,10 +1796,7 @@ module supra_framework::stake { }; event::emit_event( &mut stake_pool.distribute_rewards_events, - DistributeRewardsEvent { - pool_address, - rewards_amount, - }, + DistributeRewardsEvent { pool_address, rewards_amount } ); } @@ -1641,7 +1815,7 @@ module supra_framework::stake { num_successful_proposals: u64, num_total_proposals: u64, rewards_rate: u64, - rewards_rate_denominator: u64, + rewards_rate_denominator: u64 ): u64 { spec { // The following condition must hold because @@ -1652,13 +1826,14 @@ module supra_framework::stake { }; // The rewards amount is equal to (stake amount * rewards rate * performance multiplier). // We do multiplication in u128 before division to avoid the overflow and minimize the rounding error. - let rewards_numerator = (stake_amount as u128) * (rewards_rate as u128) * (num_successful_proposals as u128); - let rewards_denominator = (rewards_rate_denominator as u128) * (num_total_proposals as u128); + let rewards_numerator = + (stake_amount as u128) * (rewards_rate as u128) + * (num_successful_proposals as u128); + let rewards_denominator = + (rewards_rate_denominator as u128) * (num_total_proposals as u128); if (rewards_denominator > 0) { ((rewards_numerator / rewards_denominator) as u64) - } else { - 0 - } + } else { 0 } } /// Mint rewards corresponding to current epoch's `stake` and `num_successful_votes`. @@ -1667,22 +1842,22 @@ module supra_framework::stake { num_successful_proposals: u64, num_total_proposals: u64, rewards_rate: u64, - rewards_rate_denominator: u64, + rewards_rate_denominator: u64 ): u64 acquires SupraCoinCapabilities { let stake_amount = coin::value(stake); - let rewards_amount = if (stake_amount > 0) { - calculate_rewards_amount( - stake_amount, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ) - } else { - 0 - }; + let rewards_amount = + if (stake_amount > 0) { + calculate_rewards_amount( + stake_amount, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ) + } else { 0 }; if (rewards_amount > 0) { - let mint_cap = &borrow_global(@supra_framework).mint_cap; + let mint_cap = + &borrow_global(@supra_framework).mint_cap; let rewards = coin::mint(rewards_amount, mint_cap); coin::merge(stake, rewards); }; @@ -1712,13 +1887,11 @@ module supra_framework::stake { option::none() } - fun generate_validator_info(addr: address, stake_pool: &StakePool, config: ValidatorConfig): ValidatorInfo { + fun generate_validator_info( + addr: address, stake_pool: &StakePool, config: ValidatorConfig + ): ValidatorInfo { let voting_power = get_next_epoch_voting_power(stake_pool); - ValidatorInfo { - addr, - voting_power, - config, - } + ValidatorInfo { addr, voting_power, config } } /// Returns validator's next epoch voting power, including pending_active, active, and pending_inactive stake. @@ -1727,7 +1900,8 @@ module supra_framework::stake { let value_active = coin::value(&stake_pool.active); let value_pending_inactive = coin::value(&stake_pool.pending_inactive); spec { - assume value_pending_active + value_active + value_pending_inactive <= MAX_U64; + assume value_pending_active + value_active + value_pending_inactive + <= MAX_U64; }; value_pending_active + value_active + value_pending_inactive } @@ -1735,32 +1909,39 @@ module supra_framework::stake { fun update_voting_power_increase(increase_amount: u64) acquires ValidatorSet { let validator_set = borrow_global_mut(@supra_framework); let voting_power_increase_limit = - (staking_config::get_voting_power_increase_limit(&staking_config::get()) as u128); - validator_set.total_joining_power = validator_set.total_joining_power + (increase_amount as u128); + ( + staking_config::get_voting_power_increase_limit(&staking_config::get()) as u128 + ); + validator_set.total_joining_power = validator_set.total_joining_power + + (increase_amount as u128); // Only validator voting power increase if the current validator set's voting power > 0. if (validator_set.total_voting_power > 0) { assert!( - validator_set.total_joining_power <= validator_set.total_voting_power * voting_power_increase_limit / 100, - error::invalid_argument(EVOTING_POWER_INCREASE_EXCEEDS_LIMIT), + validator_set.total_joining_power + <= validator_set.total_voting_power * voting_power_increase_limit + / 100, + error::invalid_argument(EVOTING_POWER_INCREASE_EXCEEDS_LIMIT) ); } } fun assert_stake_pool_exists(pool_address: address) { - assert!(stake_pool_exists(pool_address), error::invalid_argument(ESTAKE_POOL_DOES_NOT_EXIST)); + assert!( + stake_pool_exists(pool_address), + error::invalid_argument(ESTAKE_POOL_DOES_NOT_EXIST) + ); } /// This provides an ACL for Testnet purposes. In testnet, everyone is a whale, a whale can be a validator. /// This allows a testnet to bring additional entities into the validator set without compromising the /// security of the testnet. This will NOT be enabled in Mainnet. struct AllowedValidators has key { - accounts: vector
, + accounts: vector
} public fun configure_allowed_validators( - supra_framework: &signer, - accounts: vector
+ supra_framework: &signer, accounts: vector
) acquires AllowedValidators { let supra_framework_address = signer::address_of(supra_framework); system_addresses::assert_supra_framework(supra_framework); @@ -1773,9 +1954,8 @@ module supra_framework::stake { } fun is_allowed(account: address): bool acquires AllowedValidators { - if (!exists(@supra_framework)) { - true - } else { + if (!exists(@supra_framework)) { true } + else { let allowed = borrow_global(@supra_framework); vector::contains(&allowed.accounts, &account) } @@ -1786,7 +1966,10 @@ module supra_framework::stake { } fun assert_reconfig_not_in_progress() { - assert!(!reconfiguration_state::is_in_progress(), error::invalid_state(ERECONFIGURATION_IN_PROGRESS)); + assert!( + !reconfiguration_state::is_in_progress(), + error::invalid_state(ERECONFIGURATION_IN_PROGRESS) + ); } #[test_only] @@ -1806,7 +1989,16 @@ module supra_framework::stake { #[test_only] public fun initialize_for_test(supra_framework: &signer) { reconfiguration_state::initialize(supra_framework); - initialize_for_test_custom(supra_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 1000000); + initialize_for_test_custom( + supra_framework, + 100, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 1000000 + ); } #[test_only] @@ -1814,7 +2006,7 @@ module supra_framework::stake { pk: &ed25519::UnvalidatedPublicKey, operator: &signer, pool_address: address, - should_end_epoch: bool, + should_end_epoch: bool ) acquires SupraCoinCapabilities, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { let pk_bytes = ed25519::unvalidated_public_key_to_bytes(pk); rotate_consensus_key(operator, pool_address, pk_bytes); @@ -1825,8 +2017,9 @@ module supra_framework::stake { } #[test_only] - public fun fast_forward_to_unlock(pool_address: address) - acquires SupraCoinCapabilities, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { + public fun fast_forward_to_unlock( + pool_address: address + ) acquires SupraCoinCapabilities, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { let expiration_time = get_lockup_secs(pool_address); timestamp::update_global_time_for_test_secs(expiration_time); end_epoch(); @@ -1842,7 +2035,7 @@ module supra_framework::stake { allow_validator_set_change: bool, rewards_rate_numerator: u64, rewards_rate_denominator: u64, - voting_power_increase_limit: u64, + voting_power_increase_limit: u64 ) { timestamp::set_time_has_started_for_testing(supra_framework); reconfiguration_state::initialize(supra_framework); @@ -1857,7 +2050,7 @@ module supra_framework::stake { allow_validator_set_change, rewards_rate_numerator, rewards_rate_denominator, - voting_power_increase_limit, + voting_power_increase_limit ); if (!exists(@supra_framework)) { @@ -1882,7 +2075,8 @@ module supra_framework::stake { #[test_only] public fun mint_and_add_stake( - account: &signer, amount: u64) acquires SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorSet { + account: &signer, amount: u64 + ) acquires SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorSet { mint(account, amount); add_stake(account, amount); } @@ -1893,7 +2087,7 @@ module supra_framework::stake { validator: &signer, amount: u64, should_join_validator_set: bool, - should_end_epoch: bool, + should_end_epoch: bool ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { let validator_address = signer::address_of(validator); if (!account::exists_at(signer::address_of(validator))) { @@ -1919,37 +2113,43 @@ module supra_framework::stake { public fun create_validator_set( supra_framework: &signer, active_validator_addresses: vector
, - public_keys: vector, + public_keys: vector ) { let active_validators = vector::empty(); let i = 0; while (i < vector::length(&active_validator_addresses)) { let validator_address = vector::borrow(&active_validator_addresses, i); let pk = vector::borrow(&public_keys, i); - vector::push_back(&mut active_validators, ValidatorInfo { - addr: *validator_address, - voting_power: 0, - config: ValidatorConfig { - consensus_pubkey: ed25519::unvalidated_public_key_to_bytes(pk), - network_addresses: b"", - fullnode_addresses: b"", - validator_index: 0, + vector::push_back( + &mut active_validators, + ValidatorInfo { + addr: *validator_address, + voting_power: 0, + config: ValidatorConfig { + consensus_pubkey: ed25519::unvalidated_public_key_to_bytes(pk), + network_addresses: b"", + fullnode_addresses: b"", + validator_index: 0 + } } - }); + ); i = i + 1; }; - move_to(supra_framework, ValidatorSet { - consensus_scheme: 0, - // active validators for the current epoch - active_validators, - // pending validators to leave in next epoch (still active) - pending_inactive: vector::empty(), - // pending validators to join in next epoch - pending_active: vector::empty(), - total_voting_power: 0, - total_joining_power: 0, - }); + move_to( + supra_framework, + ValidatorSet { + consensus_scheme: 0, + // active validators for the current epoch + active_validators, + // pending validators to leave in next epoch (still active) + pending_inactive: vector::empty(), + // pending validators to join in next epoch + pending_active: vector::empty(), + total_voting_power: 0, + total_joining_power: 0 + } + ); } #[test_only] @@ -1957,7 +2157,7 @@ module supra_framework::stake { account: &signer, active: Coin, pending_inactive: Coin, - locked_until_secs: u64, + locked_until_secs: u64 ) acquires AllowedValidators, OwnerCapability, StakePool, ValidatorSet { let account_address = signer::address_of(account); initialize_stake_owner(account, 0, account_address, account_address); @@ -1970,8 +2170,7 @@ module supra_framework::stake { // Allows unit tests to set custom validator performances. #[test_only] public fun update_validator_performances_for_test( - proposer_index: Option, - failed_proposer_indices: vector, + proposer_index: Option, failed_proposer_indices: vector ) acquires ValidatorPerformance { update_performance_statistics(proposer_index, failed_proposer_indices); } @@ -1986,8 +2185,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_inactive_validator_can_add_stake_if_exceeding_max_allowed( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2002,9 +2200,18 @@ module supra_framework::stake { public entry fun test_pending_active_validator_cannot_add_stake_if_exceeding_max_allowed( supra_framework: &signer, validator_1: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 100000); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 10, + 100000 + ); // Have one validator join the set to ensure the validator set is not empty when main validator joins. let (_sk_1, pk_1) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, true, true); @@ -2020,8 +2227,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_active_validator_cannot_add_stake_if_exceeding_max_allowed( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); // Validator joins validator set and waits for epoch end so it's in the validator set. @@ -2035,8 +2241,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_active_validator_with_pending_inactive_stake_cannot_add_stake_if_exceeding_max_allowed( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); // Validator joins validator set and waits for epoch end so it's in the validator set. @@ -2056,7 +2261,7 @@ module supra_framework::stake { public entry fun test_pending_inactive_cannot_add_stake_if_exceeding_max_allowed( supra_framework: &signer, validator_1: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk_1, pk_1) = generate_identity(); @@ -2073,8 +2278,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_end_to_end( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2130,8 +2334,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_inactive_validator_with_existing_lockup_join_validator_set( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2141,7 +2344,9 @@ module supra_framework::stake { increase_lockup(validator); timestamp::fast_forward_seconds(LOCKUP_CYCLE_SECONDS / 2); let validator_address = signer::address_of(validator); - assert!(get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS / 2, 1); + assert!( + get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS / 2, 1 + ); // Join the validator set with an existing lockup join_validator_set(validator, validator_address); @@ -2149,15 +2354,18 @@ module supra_framework::stake { // Validator is added to the set but lockup time shouldn't have changed. end_epoch(); assert!(get_validator_state(validator_address) == VALIDATOR_STATUS_ACTIVE, 2); - assert!(get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS / 2 - EPOCH_DURATION, 3); + assert!( + get_remaining_lockup_secs(validator_address) + == LOCKUP_CYCLE_SECONDS / 2 - EPOCH_DURATION, + 3 + ); assert_validator_state(validator_address, 100, 0, 0, 0, 0); } #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10012, location = Self)] public entry fun test_cannot_reduce_lockup( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2176,10 +2384,12 @@ module supra_framework::stake { public entry fun test_inactive_validator_cannot_join_if_exceed_increase_limit( supra_framework: &signer, validator_1: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { // Only 50% voting power increase is allowed in each epoch. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50); + initialize_for_test_custom( + supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50 + ); let (_sk_1, pk_1) = generate_identity(); let (_sk_2, pk_2) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, false, false); @@ -2198,9 +2408,18 @@ module supra_framework::stake { public entry fun test_pending_active_validator_can_add_more_stake( supra_framework: &signer, validator_1: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 10000); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 10, + 10000 + ); // Need 1 validator to be in the active validator set so joining limit works. let (_sk_1, pk_1) = generate_identity(); let (_sk_2, pk_2) = generate_identity(); @@ -2210,7 +2429,9 @@ module supra_framework::stake { // Add more stake while still pending_active. let validator_2_address = signer::address_of(validator_2); join_validator_set(validator_2, validator_2_address); - assert!(get_validator_state(validator_2_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 0); + assert!( + get_validator_state(validator_2_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 0 + ); mint_and_add_stake(validator_2, 100); assert_validator_state(validator_2_address, 200, 0, 0, 0, 0); } @@ -2220,10 +2441,12 @@ module supra_framework::stake { public entry fun test_pending_active_validator_cannot_add_more_stake_than_limit( supra_framework: &signer, validator_1: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { // 100% voting power increase is allowed in each epoch. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 100); + initialize_for_test_custom( + supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 100 + ); // Need 1 validator to be in the active validator set so joining limit works. let (_sk_1, pk_1) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, true, true); @@ -2239,18 +2462,21 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_pending_active_validator_leaves_validator_set( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); // Validator joins but epoch hasn't ended, so the validator is still pending_active. let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, true, false); let validator_address = signer::address_of(validator); - assert!(get_validator_state(validator_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 0); + assert!( + get_validator_state(validator_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 0 + ); // Check that voting power increase is tracked. - assert!(borrow_global(@supra_framework).total_joining_power == 100, 0); + assert!( + borrow_global(@supra_framework).total_joining_power == 100, 0 + ); // Leave the validator set immediately. leave_validator_set(validator, validator_address); @@ -2263,11 +2489,12 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000D, location = Self)] public entry fun test_active_validator_cannot_add_more_stake_than_limit_in_multiple_epochs( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { // Only 50% voting power increase is allowed in each epoch. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50); + initialize_for_test_custom( + supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50 + ); // Add initial stake and join the validator set. let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, true, true); @@ -2285,11 +2512,12 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000D, location = Self)] public entry fun test_active_validator_cannot_add_more_stake_than_limit( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { // Only 50% voting power increase is allowed in each epoch. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50); + initialize_for_test_custom( + supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50 + ); let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, true, true); @@ -2299,11 +2527,12 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_unlock_partial_stake( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { // Reward rate = 10%. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 100); + initialize_for_test_custom( + supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 100 + ); let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, true, true); @@ -2325,8 +2554,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_can_withdraw_all_stake_and_rewards_at_once( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2340,7 +2568,11 @@ module supra_framework::stake { assert_validator_state(validator_address, 101, 0, 0, 0, 0); // Unlock all coins while still having a lockup. - assert!(get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, 2); + assert!( + get_remaining_lockup_secs(validator_address) + == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, + 2 + ); unlock(validator, 101); assert_validator_state(validator_address, 0, 0, 0, 101, 0); @@ -2362,8 +2594,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_unlocking_more_than_available_stake_should_cap( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2376,8 +2607,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_withdraw_should_cap_by_inactive_stake( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); // Initial balance = 900 (idle) + 100 (staked) = 1000. @@ -2401,8 +2631,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_can_reactivate_pending_inactive_stake( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2420,8 +2649,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_reactivate_more_than_available_pending_inactive_stake_should_cap( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2437,8 +2665,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_active_validator_having_insufficient_remaining_stake_after_withdrawal_gets_kicked( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2466,7 +2693,7 @@ module supra_framework::stake { public entry fun test_active_validator_leaves_staking_but_still_has_a_lockup( supra_framework: &signer, validator: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk_1, pk_1) = generate_identity(); @@ -2480,7 +2707,9 @@ module supra_framework::stake { assert!(get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS, 0); leave_validator_set(validator, validator_address); // Validator is in pending_inactive state but is technically still part of the validator set. - assert!(get_validator_state(validator_address) == VALIDATOR_STATUS_PENDING_INACTIVE, 2); + assert!( + get_validator_state(validator_address) == VALIDATOR_STATUS_PENDING_INACTIVE, 2 + ); assert_validator_state(validator_address, 100, 0, 0, 0, 1); end_epoch(); @@ -2488,7 +2717,11 @@ module supra_framework::stake { assert!(get_validator_state(validator_address) == VALIDATOR_STATUS_INACTIVE, 3); // However, their stake, including rewards, should still subject to the existing lockup. assert_validator_state(validator_address, 101, 0, 0, 0, 1); - assert!(get_remaining_lockup_secs(validator_address) == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, 4); + assert!( + get_remaining_lockup_secs(validator_address) + == LOCKUP_CYCLE_SECONDS - EPOCH_DURATION, + 4 + ); // If they try to unlock, their stake is moved to pending_inactive and would only be withdrawable after the // lockup has expired. @@ -2510,7 +2743,7 @@ module supra_framework::stake { public entry fun test_active_validator_leaves_staking_and_rejoins_with_expired_lockup_should_be_renewed( supra_framework: &signer, validator: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk_1, pk_1) = generate_identity(); @@ -2541,10 +2774,12 @@ module supra_framework::stake { public entry fun test_pending_inactive_validator_does_not_count_in_increase_limit( supra_framework: &signer, validator_1: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { // Only 50% voting power increase is allowed in each epoch. - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50); + initialize_for_test_custom( + supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 10, 50 + ); let (_sk_1, pk_1) = generate_identity(); let (_sk_2, pk_2) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, true, false); @@ -2557,7 +2792,14 @@ module supra_framework::stake { mint_and_add_stake(validator_1, 51); } - #[test(supra_framework = @0x1, validator_1 = @0x123, validator_2 = @0x234, validator_3 = @0x345)] + #[ + test( + supra_framework = @0x1, + validator_1 = @0x123, + validator_2 = @0x234, + validator_3 = @0x345 + ) + ] public entry fun test_multiple_validators_join_and_leave( supra_framework: &signer, validator_1: &signer, @@ -2568,7 +2810,16 @@ module supra_framework::stake { let validator_2_address = signer::address_of(validator_2); let validator_3_address = signer::address_of(validator_3); - initialize_for_test_custom(supra_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 100, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 100 + ); let (_sk_1, pk_1) = generate_identity(); let pk_1_bytes = ed25519::unvalidated_public_key_to_bytes(&pk_1); let (_sk_2, pk_2) = generate_identity(); @@ -2602,7 +2853,11 @@ module supra_framework::stake { leave_validator_set(validator_2, validator_2_address); join_validator_set(validator_3, validator_3_address); // Validator 2 is not effectively removed until next epoch. - assert!(get_validator_state(validator_2_address) == VALIDATOR_STATUS_PENDING_INACTIVE, 6); + assert!( + get_validator_state(validator_2_address) + == VALIDATOR_STATUS_PENDING_INACTIVE, + 6 + ); assert!( vector::borrow( &borrow_global(@supra_framework).pending_inactive, @@ -2611,7 +2866,9 @@ module supra_framework::stake { 0 ); // Validator 3 is not effectively added until next epoch. - assert!(get_validator_state(validator_3_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 7); + assert!( + get_validator_state(validator_3_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 7 + ); assert!( vector::borrow( &borrow_global(@supra_framework).pending_active, @@ -2654,10 +2911,18 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_delegated_staking_with_owner_cap( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { - initialize_for_test_custom(supra_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 100, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 100 + ); let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 0, false, false); let owner_cap = extract_owner_cap(validator); @@ -2706,10 +2971,18 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000A, location = Self)] public entry fun test_validator_cannot_join_post_genesis( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { - initialize_for_test_custom(supra_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, false, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 100, + 10000, + LOCKUP_CYCLE_SECONDS, + false, + 1, + 100, + 100 + ); // Joining the validator set should fail as post genesis validator set change is not allowed. let (_sk, pk) = generate_identity(); @@ -2719,8 +2992,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000E, location = Self)] public entry fun test_invalid_pool_address( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk, pk) = generate_identity(); @@ -2731,10 +3003,18 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000A, location = Self)] public entry fun test_validator_cannot_leave_post_genesis( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { - initialize_for_test_custom(supra_framework, 100, 10000, LOCKUP_CYCLE_SECONDS, false, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 100, + 10000, + LOCKUP_CYCLE_SECONDS, + false, + 1, + 100, + 100 + ); let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, false, false); @@ -2747,21 +3027,23 @@ module supra_framework::stake { leave_validator_set(validator, validator_address); } - #[test( - supra_framework = @supra_framework, - validator_1 = @supra_framework, - validator_2 = @0x2, - validator_3 = @0x3, - validator_4 = @0x4, - validator_5 = @0x5 - )] + #[ + test( + supra_framework = @supra_framework, + validator_1 = @supra_framework, + validator_2 = @0x2, + validator_3 = @0x3, + validator_4 = @0x4, + validator_5 = @0x5 + ) + ] fun test_validator_consensus_infos_from_validator_set( supra_framework: &signer, validator_1: &signer, validator_2: &signer, validator_3: &signer, validator_4: &signer, - validator_5: &signer, + validator_5: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { let v1_addr = signer::address_of(validator_1); let v2_addr = signer::address_of(validator_2); @@ -2790,51 +3072,77 @@ module supra_framework::stake { join_validator_set(validator_1, v1_addr); join_validator_set(validator_5, v5_addr); end_epoch(); - let vci_vec_0 = validator_consensus_infos_from_validator_set(borrow_global(@supra_framework)); - let vci_addrs = vector::map_ref(&vci_vec_0, |obj|{ - let vci: &ValidatorConsensusInfo = obj; - validator_consensus_info::get_addr(vci) - }); - let vci_pks = vector::map_ref(&vci_vec_0, |obj|{ - let vci: &ValidatorConsensusInfo = obj; - validator_consensus_info::get_pk_bytes(vci) - }); - let vci_voting_powers = vector::map_ref(&vci_vec_0, |obj|{ - let vci: &ValidatorConsensusInfo = obj; - validator_consensus_info::get_voting_power(vci) - }); + let vci_vec_0 = + validator_consensus_infos_from_validator_set( + borrow_global(@supra_framework) + ); + let vci_addrs = vector::map_ref( + &vci_vec_0, + |obj| { + let vci: &ValidatorConsensusInfo = obj; + validator_consensus_info::get_addr(vci) + } + ); + let vci_pks = vector::map_ref( + &vci_vec_0, + |obj| { + let vci: &ValidatorConsensusInfo = obj; + validator_consensus_info::get_pk_bytes(vci) + } + ); + let vci_voting_powers = vector::map_ref( + &vci_vec_0, + |obj| { + let vci: &ValidatorConsensusInfo = obj; + validator_consensus_info::get_voting_power(vci) + } + ); assert!(vector[@0x5, @supra_framework, @0x3] == vci_addrs, 1); // assert!(vector[pk_5_bytes, pk_1_bytes, pk_3_bytes] == vci_pks, 2); assert!(vector[105, 101, 103] == vci_voting_powers, 3); leave_validator_set(validator_3, v3_addr); - let vci_vec_1 = validator_consensus_infos_from_validator_set(borrow_global(@supra_framework)); + let vci_vec_1 = + validator_consensus_infos_from_validator_set( + borrow_global(@supra_framework) + ); assert!(vci_vec_0 == vci_vec_1, 11); join_validator_set(validator_2, v2_addr); - let vci_vec_2 = validator_consensus_infos_from_validator_set(borrow_global(@supra_framework)); + let vci_vec_2 = + validator_consensus_infos_from_validator_set( + borrow_global(@supra_framework) + ); assert!(vci_vec_0 == vci_vec_2, 12); leave_validator_set(validator_1, v1_addr); - let vci_vec_3 = validator_consensus_infos_from_validator_set(borrow_global(@supra_framework)); + let vci_vec_3 = + validator_consensus_infos_from_validator_set( + borrow_global(@supra_framework) + ); assert!(vci_vec_0 == vci_vec_3, 13); join_validator_set(validator_4, v4_addr); - let vci_vec_4 = validator_consensus_infos_from_validator_set(borrow_global(@supra_framework)); + let vci_vec_4 = + validator_consensus_infos_from_validator_set( + borrow_global(@supra_framework) + ); assert!(vci_vec_0 == vci_vec_4, 14); } - #[test( - supra_framework = @supra_framework, - validator_1 = @supra_framework, - validator_2 = @0x2, - validator_3 = @0x3, - validator_4 = @0x4, - validator_5 = @0x5 - )] + #[ + test( + supra_framework = @supra_framework, + validator_1 = @supra_framework, + validator_2 = @0x2, + validator_3 = @0x3, + validator_4 = @0x4, + validator_5 = @0x5 + ) + ] public entry fun test_staking_validator_index( supra_framework: &signer, validator_1: &signer, validator_2: &signer, validator_3: &signer, validator_4: &signer, - validator_5: &signer, + validator_5: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { let v1_addr = signer::address_of(validator_1); let v2_addr = signer::address_of(validator_2); @@ -2897,7 +3205,7 @@ module supra_framework::stake { public entry fun test_validator_rewards_are_performance_based( supra_framework: &signer, validator_1: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); @@ -2912,8 +3220,10 @@ module supra_framework::stake { // Validator 2 failed proposal. let failed_proposer_indices = vector::empty(); - let validator_1_index = borrow_global(validator_1_address).validator_index; - let validator_2_index = borrow_global(validator_2_address).validator_index; + let validator_1_index = + borrow_global(validator_1_address).validator_index; + let validator_2_index = + borrow_global(validator_2_address).validator_index; vector::push_back(&mut failed_proposer_indices, validator_2_index); let proposer_indices = option::some(validator_1_index); update_performance_statistics(proposer_indices, failed_proposer_indices); @@ -2927,8 +3237,10 @@ module supra_framework::stake { unlock(validator_2, 100); leave_validator_set(validator_2, validator_2_address); let failed_proposer_indices = vector::empty(); - let validator_1_index = borrow_global(validator_1_address).validator_index; - let validator_2_index = borrow_global(validator_2_address).validator_index; + let validator_1_index = + borrow_global(validator_1_address).validator_index; + let validator_2_index = + borrow_global(validator_2_address).validator_index; vector::push_back(&mut failed_proposer_indices, validator_1_index); vector::push_back(&mut failed_proposer_indices, validator_2_index); update_performance_statistics(option::none(), failed_proposer_indices); @@ -2945,7 +3257,7 @@ module supra_framework::stake { public entry fun test_validator_rewards_rate_decrease_over_time( supra_framework: &signer, validator_1: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); @@ -2973,9 +3285,13 @@ module supra_framework::stake { fixed_point64::create_from_rational(3, 1000), one_year_in_secs, genesis_time_in_secs, - fixed_point64::create_from_rational(50, 100), + fixed_point64::create_from_rational(50, 100) + ); + features::change_feature_flags_for_testing( + supra_framework, + vector[features::get_periodical_reward_rate_decrease_feature()], + vector[] ); - features::change_feature_flags_for_testing(supra_framework, vector[features::get_periodical_reward_rate_decrease_feature()], vector[]); // For some reason, this epoch is very long. It has been 1 year since genesis when the epoch ends. timestamp::fast_forward_seconds(one_year_in_secs - EPOCH_DURATION * 3); @@ -3000,8 +3316,7 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_update_performance_statistics_should_not_fail_due_to_out_of_bounds( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); @@ -3009,7 +3324,8 @@ module supra_framework::stake { let (_sk, pk) = generate_identity(); initialize_test_validator(&pk, validator, 100, true, true); - let valid_validator_index = borrow_global(validator_address).validator_index; + let valid_validator_index = + borrow_global(validator_address).validator_index; let out_of_bounds_index = valid_validator_index + 100; // Invalid validator index in the failed proposers vector should not lead to abort. @@ -3031,10 +3347,18 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x1000B, location = Self)] public entry fun test_invalid_config( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorSet { - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 100 + ); // Call initialize_stake_owner, which only initializes the stake pool but not validator config. let validator_address = signer::address_of(validator); @@ -3049,10 +3373,18 @@ module supra_framework::stake { #[test(supra_framework = @supra_framework, validator = @0x123)] public entry fun test_valid_config( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorSet { - initialize_for_test_custom(supra_framework, 50, 10000, LOCKUP_CYCLE_SECONDS, true, 1, 100, 100); + initialize_for_test_custom( + supra_framework, + 50, + 10000, + LOCKUP_CYCLE_SECONDS, + true, + 1, + 100, + 100 + ); // Call initialize_stake_owner, which only initializes the stake pool but not validator config. let validator_address = signer::address_of(validator); @@ -3077,13 +3409,14 @@ module supra_framework::stake { let num_total_proposals = 200; let rewards_rate = 700; let rewards_rate_denominator = 777; - let rewards_amount = calculate_rewards_amount( - stake_amount, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ); + let rewards_amount = + calculate_rewards_amount( + stake_amount, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); // Consider `amount_imprecise` and `amount_precise` defined as follows: // amount_imprecise = (stake_amount * rewards_rate / rewards_rate_denominator) * num_successful_proposals / num_total_proposals // amount_precise = stake_amount * rewards_rate * num_successful_proposals / (rewards_rate_denominator * num_total_proposals) @@ -3098,50 +3431,67 @@ module supra_framework::stake { let rewards_rate = 3141592; let rewards_rate_denominator = 10000000; // This should not abort due to an arithmetic overflow. - let rewards_amount = calculate_rewards_amount( - stake_amount, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator - ); + let rewards_amount = + calculate_rewards_amount( + stake_amount, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); assert!(rewards_amount == 31412778408000000, 0); } #[test_only] public fun set_validator_perf_at_least_one_block() acquires ValidatorPerformance { let validator_perf = borrow_global_mut(@supra_framework); - vector::for_each_mut(&mut validator_perf.validators, |validator|{ - let validator: &mut IndividualValidatorPerformance = validator; - if (validator.successful_proposals + validator.failed_proposals < 1) { - validator.successful_proposals = 1; - }; - }); + vector::for_each_mut( + &mut validator_perf.validators, + |validator| { + let validator: &mut IndividualValidatorPerformance = validator; + if (validator.successful_proposals + validator.failed_proposals < 1) { + validator.successful_proposals = 1; + }; + } + ); } #[test(supra_framework = @0x1, validator_1 = @0x123, validator_2 = @0x234)] public entry fun test_removing_validator_from_active_set( supra_framework: &signer, validator_1: &signer, - validator_2: &signer, + validator_2: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { initialize_for_test(supra_framework); let (_sk_1, pk_1) = generate_identity(); let (_sk_2, pk_2) = generate_identity(); initialize_test_validator(&pk_1, validator_1, 100, true, false); initialize_test_validator(&pk_2, validator_2, 100, true, true); - assert!(vector::length(&borrow_global(@supra_framework).active_validators) == 2, 0); + assert!( + vector::length( + &borrow_global(@supra_framework).active_validators + ) == 2, + 0 + ); // Remove validator 1 from the active validator set. Only validator 2 remains. let validator_to_remove = signer::address_of(validator_1); remove_validators(supra_framework, &vector[validator_to_remove]); - assert!(vector::length(&borrow_global(@supra_framework).active_validators) == 1, 0); - assert!(get_validator_state(validator_to_remove) == VALIDATOR_STATUS_PENDING_INACTIVE, 1); + assert!( + vector::length( + &borrow_global(@supra_framework).active_validators + ) == 1, + 0 + ); + assert!( + get_validator_state(validator_to_remove) + == VALIDATOR_STATUS_PENDING_INACTIVE, + 1 + ); } #[test_only] - public fun end_epoch( - ) acquires StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { + public fun end_epoch() acquires StakePool, SupraCoinCapabilities, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { // Set the number of blocks to 1, to give out rewards to non-failing validators. set_validator_perf_at_least_one_block(); timestamp::fast_forward_seconds(EPOCH_DURATION); @@ -3156,7 +3506,7 @@ module supra_framework::stake { active_stake: u64, inactive_stake: u64, pending_active_stake: u64, - pending_inactive_stake: u64, + pending_inactive_stake: u64 ) acquires StakePool { let stake_pool = borrow_global(pool_address); let actual_active_stake = coin::value(&stake_pool.active); @@ -3164,9 +3514,15 @@ module supra_framework::stake { let actual_inactive_stake = coin::value(&stake_pool.inactive); assert!(actual_inactive_stake == inactive_stake, actual_inactive_stake); let actual_pending_active_stake = coin::value(&stake_pool.pending_active); - assert!(actual_pending_active_stake == pending_active_stake, actual_pending_active_stake); + assert!( + actual_pending_active_stake == pending_active_stake, + actual_pending_active_stake + ); let actual_pending_inactive_stake = coin::value(&stake_pool.pending_inactive); - assert!(actual_pending_inactive_stake == pending_inactive_stake, actual_pending_inactive_stake); + assert!( + actual_pending_inactive_stake == pending_inactive_stake, + actual_pending_inactive_stake + ); } #[test_only] @@ -3176,17 +3532,25 @@ module supra_framework::stake { inactive_stake: u64, pending_active_stake: u64, pending_inactive_stake: u64, - validator_index: u64, + validator_index: u64 ) acquires StakePool, ValidatorConfig { - assert_stake_pool(pool_address, active_stake, inactive_stake, pending_active_stake, pending_inactive_stake); + assert_stake_pool( + pool_address, + active_stake, + inactive_stake, + pending_active_stake, + pending_inactive_stake + ); let validator_config = borrow_global(pool_address); - assert!(validator_config.validator_index == validator_index, validator_config.validator_index); + assert!( + validator_config.validator_index == validator_index, + validator_config.validator_index + ); } #[test(supra_framework = @0x1, validator = @0x123)] public entry fun test_allowed_validators( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, ValidatorSet { let addr = signer::address_of(validator); let (burn, mint) = supra_coin::initialize_for_test(supra_framework); @@ -3202,8 +3566,7 @@ module supra_framework::stake { #[test(supra_framework = @0x1, validator = @0x123)] #[expected_failure(abort_code = 0x60011, location = Self)] public entry fun test_not_allowed_validators( - supra_framework: &signer, - validator: &signer, + supra_framework: &signer, validator: &signer ) acquires AllowedValidators, OwnerCapability, StakePool, ValidatorSet { configure_allowed_validators(supra_framework, vector[]); let (burn, mint) = supra_coin::initialize_for_test(supra_framework); @@ -3218,7 +3581,8 @@ module supra_framework::stake { #[test_only] public fun with_rewards(amount: u64): u64 { - let (numerator, denominator) = staking_config::get_reward_rate(&staking_config::get()); + let (numerator, denominator) = + staking_config::get_reward_rate(&staking_config::get()); amount + amount * numerator / denominator } @@ -3238,15 +3602,24 @@ module supra_framework::stake { #[test_only] const COLLECT_AND_DISTRIBUTE_GAS_FEES: u64 = 6; - #[test(supra_framework = @0x1, validator_1 = @0x123, validator_2 = @0x234, validator_3 = @0x345)] + #[ + test( + supra_framework = @0x1, + validator_1 = @0x123, + validator_2 = @0x234, + validator_3 = @0x345 + ) + ] fun test_distribute_validator_fees( supra_framework: &signer, validator_1: &signer, validator_2: &signer, - validator_3: &signer, + validator_3: &signer ) acquires AllowedValidators, SupraCoinCapabilities, OwnerCapability, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { // Make sure that fees collection and distribution is enabled. - features::change_feature_flags_for_testing(supra_framework, vector[COLLECT_AND_DISTRIBUTE_GAS_FEES], vector[]); + features::change_feature_flags_for_testing( + supra_framework, vector[COLLECT_AND_DISTRIBUTE_GAS_FEES], vector[] + ); assert!(features::collect_and_distribute_gas_fees(), 0); // Initialize staking and validator fees table. diff --git a/aptos-move/framework/supra-framework/sources/stake.spec.move b/aptos-move/framework/supra-framework/sources/stake.spec.move index 374b545c55958..d7180c56b010e 100644 --- a/aptos-move/framework/supra-framework/sources/stake.spec.move +++ b/aptos-move/framework/supra-framework/sources/stake.spec.move @@ -43,11 +43,15 @@ spec supra_framework::stake { spec module { pragma verify = true; // The validator set should satisfy its desired invariant. - invariant [suspendable] exists(@supra_framework) ==> validator_set_is_valid(); + invariant [suspendable] exists(@supra_framework) ==> + validator_set_is_valid(); // After genesis, `SupraCoinCapabilities`, `ValidatorPerformance` and `ValidatorSet` exist. - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); // property 2: The owner of a validator remains immutable. apply ValidatorOwnerNoChange to *; @@ -70,22 +74,34 @@ spec supra_framework::stake { } spec schema ValidatorNotChangeDuringReconfig { - ensures (reconfiguration_state::spec_is_in_progress() && old(exists(@supra_framework))) ==> - old(global(@supra_framework)) == global(@supra_framework); + ensures ( + reconfiguration_state::spec_is_in_progress() + && old(exists(@supra_framework)) + ) ==> + old(global(@supra_framework)) + == global(@supra_framework); } spec schema StakePoolNotChangeDuringReconfig { - ensures forall a: address where old(exists(a)): reconfiguration_state::spec_is_in_progress() ==> - (old(global(a).pending_inactive) == global(a).pending_inactive && - old(global(a).pending_active) == global(a).pending_active && - old(global(a).inactive) == global(a).inactive && - old(global(a).active) == global(a).active); + ensures forall a: address where old(exists(a)): + reconfiguration_state::spec_is_in_progress() ==> + ( + old(global(a).pending_inactive) + == global(a).pending_inactive + && old(global(a).pending_active) + == global(a).pending_active + && old(global(a).inactive) + == global(a).inactive + && old(global(a).active) + == global(a).active + ); } spec schema ValidatorOwnerNoChange { /// [high-level-req-2] ensures forall addr: address where old(exists(addr)): - old(global(addr)).pool_address == global(addr).pool_address; + old(global(addr)).pool_address + == global(addr).pool_address; } // property 3: The total staked value in the stake pool should be constant (excluding adding and withdrawing operations). @@ -94,8 +110,11 @@ spec supra_framework::stake { let stake_pool = global(pool_address); let post post_stake_pool = global(pool_address); /// [high-level-req-3] - ensures stake_pool.active.value + stake_pool.inactive.value + stake_pool.pending_active.value + stake_pool.pending_inactive.value == - post_stake_pool.active.value + post_stake_pool.inactive.value + post_stake_pool.pending_active.value + post_stake_pool.pending_inactive.value; + ensures stake_pool.active.value + stake_pool.inactive.value + + stake_pool.pending_active.value + stake_pool.pending_inactive.value + == post_stake_pool.active.value + post_stake_pool.inactive.value + + post_stake_pool.pending_active.value + + post_stake_pool.pending_inactive.value; } // A desired invariant for the validator set. @@ -105,15 +124,14 @@ spec supra_framework::stake { } spec fun validator_set_is_valid_impl(validator_set: ValidatorSet): bool { - spec_validators_are_initialized(validator_set.active_validators) && - spec_validators_are_initialized(validator_set.pending_inactive) && - spec_validators_are_initialized(validator_set.pending_active) && - spec_validator_indices_are_valid(validator_set.active_validators) && - spec_validator_indices_are_valid(validator_set.pending_inactive) + spec_validators_are_initialized(validator_set.active_validators) + && spec_validators_are_initialized(validator_set.pending_inactive) + && spec_validators_are_initialized(validator_set.pending_active) + && spec_validator_indices_are_valid(validator_set.active_validators) + && spec_validator_indices_are_valid(validator_set.pending_inactive) && spec_validator_indices_active_pending_inactive(validator_set) } - // ----------------------- // Function specifications // ----------------------- @@ -129,30 +147,34 @@ spec supra_framework::stake { account: &signer, consensus_pubkey: vector, network_addresses: vector, - fullnode_addresses: vector, - ){ + fullnode_addresses: vector + ) { let is_public_key_validated = ed25519::spec_public_key_validate_internal( - consensus_pubkey, + consensus_pubkey ); aborts_if !is_public_key_validated; let addr = signer::address_of(account); let post_addr = signer::address_of(account); let allowed = global(@supra_framework); aborts_if exists(addr); - aborts_if exists(@supra_framework) && !vector::spec_contains(allowed.accounts, addr); + aborts_if exists(@supra_framework) + && !vector::spec_contains(allowed.accounts, addr); aborts_if stake_pool_exists(addr); aborts_if exists(addr); aborts_if !exists(addr); aborts_if global(addr).guid_creation_num + 12 > MAX_U64; - aborts_if global(addr).guid_creation_num + 12 >= account::MAX_GUID_CREATION_NUM; + aborts_if global(addr).guid_creation_num + 12 + >= account::MAX_GUID_CREATION_NUM; ensures exists(post_addr); - ensures global(post_addr) == OwnerCapability { pool_address: post_addr }; - ensures global(post_addr) == ValidatorConfig { - consensus_pubkey, - network_addresses, - fullnode_addresses, - validator_index: 0, - }; + ensures global(post_addr) + == OwnerCapability { pool_address: post_addr }; + ensures global(post_addr) + == ValidatorConfig { + consensus_pubkey, + network_addresses, + fullnode_addresses, + validator_index: 0 + }; } // `Validator` is initialized once. @@ -167,11 +189,7 @@ spec supra_framework::stake { ensures exists(aptos_addr); } - spec join_validator_set( - operator: &signer, - pool_address: address - ) - { + spec join_validator_set(operator: &signer, pool_address: address) { // This function casue timeout (property proved) // pragma verify_duration_estimate = 120; pragma disable_invariants_in_body; @@ -186,9 +204,15 @@ spec supra_framework::stake { let validator_set = global(@supra_framework); let post p_validator_set = global(@supra_framework); aborts_if signer::address_of(operator) != stake_pool.operator_address; - aborts_if option::spec_is_some(spec_find_validator(validator_set.active_validators, pool_address)) || - option::spec_is_some(spec_find_validator(validator_set.pending_inactive, pool_address)) || - option::spec_is_some(spec_find_validator(validator_set.pending_active, pool_address)); + aborts_if option::spec_is_some( + spec_find_validator(validator_set.active_validators, pool_address) + ) + || option::spec_is_some( + spec_find_validator(validator_set.pending_inactive, pool_address) + ) + || option::spec_is_some( + spec_find_validator(validator_set.pending_active, pool_address) + ); let config = staking_config::get(); let voting_power = get_next_epoch_voting_power(stake_pool); @@ -196,36 +220,38 @@ spec supra_framework::stake { let minimum_stake = config.minimum_stake; let maximum_stake = config.maximum_stake; aborts_if voting_power < minimum_stake; - aborts_if voting_power >maximum_stake; + aborts_if voting_power > maximum_stake; let validator_config = global(pool_address); aborts_if vector::is_empty(validator_config.consensus_pubkey); - let validator_set_size = vector::length(validator_set.active_validators) + vector::length(validator_set.pending_active) + 1; + let validator_set_size = vector::length(validator_set.active_validators) + + vector::length(validator_set.pending_active) + 1; aborts_if validator_set_size > MAX_VALIDATOR_SET_SIZE; - let voting_power_increase_limit = (staking_config::get_voting_power_increase_limit(config) as u128); + let voting_power_increase_limit = ( + staking_config::get_voting_power_increase_limit(config) as u128 + ); aborts_if (validator_set.total_joining_power + (voting_power as u128)) > MAX_U128; - aborts_if validator_set.total_voting_power * voting_power_increase_limit > MAX_U128; - aborts_if validator_set.total_voting_power > 0 && - (validator_set.total_joining_power + (voting_power as u128)) * 100 > validator_set.total_voting_power * voting_power_increase_limit; + aborts_if validator_set.total_voting_power * voting_power_increase_limit + > MAX_U128; + aborts_if validator_set.total_voting_power > 0 + && (validator_set.total_joining_power + (voting_power as u128)) * 100 + > validator_set.total_voting_power * voting_power_increase_limit; let post p_validator_info = ValidatorInfo { addr: pool_address, voting_power, - config: validator_config, + config: validator_config }; - ensures validator_set.total_joining_power + voting_power == p_validator_set.total_joining_power; + ensures validator_set.total_joining_power + voting_power + == p_validator_set.total_joining_power; ensures vector::spec_contains(p_validator_set.pending_active, p_validator_info); } - spec withdraw( - owner: &signer, - withdraw_amount: u64 - ) - { + spec withdraw(owner: &signer, withdraw_amount: u64) { // TODO(fa_migration) pragma verify = false; aborts_if reconfiguration_state::spec_is_in_progress(); @@ -238,33 +264,53 @@ spec supra_framework::stake { aborts_if !exists(@supra_framework); let validator_set = global(@supra_framework); - let bool_find_validator = !option::spec_is_some(spec_find_validator(validator_set.active_validators, pool_address)) && - !option::spec_is_some(spec_find_validator(validator_set.pending_inactive, pool_address)) && - !option::spec_is_some(spec_find_validator(validator_set.pending_active, pool_address)); - aborts_if bool_find_validator && !exists(@supra_framework); - let new_withdraw_amount_1 = min(withdraw_amount, stake_pool.inactive.value + stake_pool.pending_inactive.value); + let bool_find_validator = !option::spec_is_some( + spec_find_validator(validator_set.active_validators, pool_address) + ) + && !option::spec_is_some( + spec_find_validator(validator_set.pending_inactive, pool_address) + ) + && !option::spec_is_some( + spec_find_validator(validator_set.pending_active, pool_address) + ); + aborts_if bool_find_validator + && !exists(@supra_framework); + let new_withdraw_amount_1 = min( + withdraw_amount, stake_pool.inactive.value + + stake_pool.pending_inactive.value + ); let new_withdraw_amount_2 = min(withdraw_amount, stake_pool.inactive.value); - aborts_if bool_find_validator && timestamp::now_seconds() > stake_pool.locked_until_secs && - new_withdraw_amount_1 > 0 && stake_pool.inactive.value + stake_pool.pending_inactive.value < new_withdraw_amount_1; - aborts_if !(bool_find_validator && exists(@supra_framework)) && - new_withdraw_amount_2 > 0 && stake_pool.inactive.value < new_withdraw_amount_2; + aborts_if bool_find_validator + && timestamp::now_seconds() > stake_pool.locked_until_secs + && new_withdraw_amount_1 > 0 + && stake_pool.inactive.value + stake_pool.pending_inactive.value + < new_withdraw_amount_1; + aborts_if !( + bool_find_validator + && exists(@supra_framework) + ) + && new_withdraw_amount_2 > 0 + && stake_pool.inactive.value < new_withdraw_amount_2; aborts_if !exists>(addr); - include coin::DepositAbortsIf{account_addr: addr}; + include coin::DepositAbortsIf { account_addr: addr }; let coin_store = global>(addr); let post p_coin_store = global>(addr); - ensures bool_find_validator && timestamp::now_seconds() > stake_pool.locked_until_secs - && exists(addr) && exists>(addr) ==> - coin_store.coin.value + new_withdraw_amount_1 == p_coin_store.coin.value; - ensures !(bool_find_validator && exists(@supra_framework)) - && exists(addr) && exists>(addr) ==> - coin_store.coin.value + new_withdraw_amount_2 == p_coin_store.coin.value; - } - - spec leave_validator_set( - operator: &signer, - pool_address: address - ) { + ensures bool_find_validator + && timestamp::now_seconds() > stake_pool.locked_until_secs + && exists(addr) + && exists>(addr) ==> + coin_store.coin.value + new_withdraw_amount_1 == p_coin_store.coin.value; + ensures !( + bool_find_validator + && exists(@supra_framework) + ) + && exists(addr) + && exists>(addr) ==> + coin_store.coin.value + new_withdraw_amount_2 == p_coin_store.coin.value; + } + + spec leave_validator_set(operator: &signer, pool_address: address) { pragma disable_invariants_in_body; requires chain_status::is_operating(); aborts_if reconfiguration_state::spec_is_in_progress(); @@ -277,7 +323,9 @@ spec supra_framework::stake { aborts_if signer::address_of(operator) != stake_pool.operator_address; let validator_set = global(@supra_framework); - let validator_find_bool = option::spec_is_some(spec_find_validator(validator_set.pending_active, pool_address)); + let validator_find_bool = option::spec_is_some( + spec_find_validator(validator_set.pending_active, pool_address) + ); let active_validators = validator_set.active_validators; let pending_active = validator_set.pending_active; @@ -285,18 +333,31 @@ spec supra_framework::stake { let post post_active_validators = post_validator_set.active_validators; let pending_inactive_validators = validator_set.pending_inactive; let post post_pending_inactive_validators = post_validator_set.pending_inactive; - ensures len(active_validators) + len(pending_inactive_validators) == len(post_active_validators) - + len(post_pending_inactive_validators); - - aborts_if !validator_find_bool && !option::spec_is_some(spec_find_validator(active_validators, pool_address)); - aborts_if !validator_find_bool && vector::length(validator_set.active_validators) <= option::spec_borrow(spec_find_validator(active_validators, pool_address)); - aborts_if !validator_find_bool && vector::length(validator_set.active_validators) < 2; - aborts_if validator_find_bool && vector::length(validator_set.pending_active) <= option::spec_borrow(spec_find_validator(pending_active, pool_address)); + ensures len(active_validators) + len(pending_inactive_validators) + == len(post_active_validators) + len(post_pending_inactive_validators); + + aborts_if !validator_find_bool + && !option::spec_is_some(spec_find_validator(active_validators, pool_address)); + aborts_if !validator_find_bool + && vector::length(validator_set.active_validators) + <= option::spec_borrow( + spec_find_validator(active_validators, pool_address) + ); + aborts_if !validator_find_bool + && vector::length(validator_set.active_validators) < 2; + aborts_if validator_find_bool + && vector::length(validator_set.pending_active) + <= option::spec_borrow(spec_find_validator(pending_active, pool_address)); let post p_validator_set = global(@supra_framework); let validator_stake = (get_next_epoch_voting_power(stake_pool) as u128); - ensures validator_find_bool && validator_set.total_joining_power > validator_stake ==> - p_validator_set.total_joining_power == validator_set.total_joining_power - validator_stake; - ensures !validator_find_bool ==> !option::spec_is_some(spec_find_validator(p_validator_set.pending_active, pool_address)); + ensures validator_find_bool + && validator_set.total_joining_power > validator_stake ==> + p_validator_set.total_joining_power + == validator_set.total_joining_power - validator_stake; + ensures !validator_find_bool ==> + !option::spec_is_some( + spec_find_validator(p_validator_set.pending_active, pool_address) + ); } spec extract_owner_cap(owner: &signer): OwnerCapability { @@ -324,10 +385,11 @@ spec supra_framework::stake { aborts_if amount != 0 && !exists(pool_address); modifies global(pool_address); include StakedValueNochange; - let min_amount = aptos_std::math64::min(amount,pre_stake_pool.active.value); + let min_amount = aptos_std::math64::min(amount, pre_stake_pool.active.value); ensures stake_pool.active.value == pre_stake_pool.active.value - min_amount; - ensures stake_pool.pending_inactive.value == pre_stake_pool.pending_inactive.value + min_amount; + ensures stake_pool.pending_inactive.value + == pre_stake_pool.pending_inactive.value + min_amount; } // Only active validator can update locked_until_secs. @@ -354,7 +416,7 @@ spec supra_framework::stake { operator: &signer, pool_address: address, new_network_addresses: vector, - new_fullnode_addresses: vector, + new_fullnode_addresses: vector ) { let pre_stake_pool = global(pool_address); let post validator_info = global(pool_address); @@ -390,16 +452,17 @@ spec supra_framework::stake { let pre_stake_pool = global(pool_address); let post stake_pool = global(pool_address); modifies global(pool_address); - let min_amount = aptos_std::math64::min(amount, pre_stake_pool.pending_inactive.value); + let min_amount = aptos_std::math64::min( + amount, pre_stake_pool.pending_inactive.value + ); - ensures stake_pool.pending_inactive.value == pre_stake_pool.pending_inactive.value - min_amount; + ensures stake_pool.pending_inactive.value + == pre_stake_pool.pending_inactive.value - min_amount; ensures stake_pool.active.value == pre_stake_pool.active.value + min_amount; } spec rotate_consensus_key( - operator: &signer, - pool_address: address, - new_consensus_pubkey: vector, + operator: &signer, pool_address: address, new_consensus_pubkey: vector ) { let pre_stake_pool = global(pool_address); let post validator_info = global(pool_address); @@ -408,7 +471,7 @@ spec supra_framework::stake { aborts_if signer::address_of(operator) != pre_stake_pool.operator_address; aborts_if !exists(pool_address); let is_public_key_validated = ed25519::spec_public_key_validate_internal( - new_consensus_pubkey, + new_consensus_pubkey ); aborts_if !is_public_key_validated; modifies global(pool_address); @@ -421,7 +484,7 @@ spec supra_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, - genesis: bool, + genesis: bool ) { modifies global(pool_address); } @@ -458,9 +521,15 @@ spec supra_framework::stake { let validator_perf = global(@supra_framework); let post post_validator_perf = global(@supra_framework); let validator_len = len(validator_perf.validators); - ensures (option::spec_is_some(ghost_proposer_idx) && option::spec_borrow(ghost_proposer_idx) < validator_len) ==> - (post_validator_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals == - validator_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals + 1); + ensures ( + option::spec_is_some(ghost_proposer_idx) + && option::spec_borrow(ghost_proposer_idx) < validator_len + ) ==> + ( + post_validator_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals == + validator_perf.validators[option::spec_borrow(ghost_proposer_idx)].successful_proposals + + 1 + ); } spec next_validator_consensus_infos { @@ -469,7 +538,8 @@ spec supra_framework::stake { aborts_if false; include ResourceRequirement; include GetReconfigStartTimeRequirement; - include features::spec_periodical_reward_rate_decrease_enabled() ==> staking_config::StakingRewardsConfigEnabledRequirement; + include features::spec_periodical_reward_rate_decrease_enabled() ==> + staking_config::StakingRewardsConfigEnabledRequirement; } spec update_stake_pool { @@ -485,19 +555,28 @@ spec supra_framework::stake { let validator_config = global(pool_address); let cur_validator_perf = validator_perf.validators[validator_config.validator_index]; let num_successful_proposals = cur_validator_perf.successful_proposals; - let num_total_proposals = cur_validator_perf.successful_proposals + cur_validator_perf.failed_proposals; + let num_total_proposals = cur_validator_perf.successful_proposals + + cur_validator_perf.failed_proposals; let rewards_rate = spec_get_reward_rate_1(staking_config); let rewards_rate_denominator = spec_get_reward_rate_2(staking_config); let rewards_amount_1 = if (stake_pool.active.value > 0) { - spec_rewards_amount(stake_pool.active.value, num_successful_proposals, num_total_proposals, rewards_rate, rewards_rate_denominator) - } else { - 0 - }; + spec_rewards_amount( + stake_pool.active.value, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ) + } else { 0 }; let rewards_amount_2 = if (stake_pool.pending_inactive.value > 0) { - spec_rewards_amount(stake_pool.pending_inactive.value, num_successful_proposals, num_total_proposals, rewards_rate, rewards_rate_denominator) - } else { - 0 - }; + spec_rewards_amount( + stake_pool.pending_inactive.value, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ) + } else { 0 }; let post post_stake_pool = global(pool_address); let post post_active_value = post_stake_pool.active.value; let post post_pending_inactive_value = post_stake_pool.pending_inactive.value; @@ -506,18 +585,27 @@ spec supra_framework::stake { let post post_inactive_value = post_stake_pool.inactive.value; ensures post_stake_pool.pending_active.value == 0; // the amount stored in the stake pool should not changed after the update - ensures if (features::spec_is_enabled(features::COLLECT_AND_DISTRIBUTE_GAS_FEES) && table::spec_contains(fees_table, pool_address)) { - !table::spec_contains(post_fees_table, pool_address) && - post_active_value == stake_pool.active.value + rewards_amount_1 + stake_pool.pending_active.value + table::spec_get(fees_table, pool_address).value + ensures if (features::spec_is_enabled(features::COLLECT_AND_DISTRIBUTE_GAS_FEES) + && table::spec_contains(fees_table, pool_address)) { + !table::spec_contains(post_fees_table, pool_address) + && post_active_value + == stake_pool.active.value + rewards_amount_1 + + stake_pool.pending_active.value + + table::spec_get(fees_table, pool_address).value } else { - post_active_value == stake_pool.active.value + rewards_amount_1 + stake_pool.pending_active.value + post_active_value + == stake_pool.active.value + rewards_amount_1 + + stake_pool.pending_active.value }; // when current lockup cycle has expired, pending inactive should be fully unlocked and moved into inactive ensures if (spec_get_reconfig_start_time_secs() >= stake_pool.locked_until_secs) { - post_pending_inactive_value == 0 && - post_inactive_value == stake_pool.inactive.value + stake_pool.pending_inactive.value + rewards_amount_2 + post_pending_inactive_value == 0 + && post_inactive_value + == stake_pool.inactive.value + stake_pool.pending_inactive.value + + rewards_amount_2 } else { - post_pending_inactive_value == stake_pool.pending_inactive.value + rewards_amount_2 + post_pending_inactive_value + == stake_pool.pending_inactive.value + rewards_amount_2 }; } @@ -529,15 +617,16 @@ spec supra_framework::stake { aborts_if !exists(pool_address); aborts_if !exists(pool_address); - aborts_if global(pool_address).validator_index >= len(validator_perf.validators); + aborts_if global(pool_address).validator_index + >= len(validator_perf.validators); let aptos_addr = type_info::type_of().account_address; aborts_if !exists(aptos_addr); let stake_pool = global(pool_address); - include DistributeRewardsAbortsIf {stake: stake_pool.active}; - include DistributeRewardsAbortsIf {stake: stake_pool.pending_inactive}; + include DistributeRewardsAbortsIf { stake: stake_pool.active }; + include DistributeRewardsAbortsIf { stake: stake_pool.pending_inactive }; } spec distribute_rewards { @@ -550,21 +639,27 @@ spec supra_framework::stake { include DistributeRewardsAbortsIf; ensures old(stake.value) > 0 ==> - result == spec_rewards_amount( - old(stake.value), - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator); + result + == spec_rewards_amount( + old(stake.value), + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); ensures old(stake.value) > 0 ==> - stake.value == old(stake.value) + spec_rewards_amount( - old(stake.value), - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator); + stake.value + == old(stake.value) + + spec_rewards_amount( + old(stake.value), + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); ensures old(stake.value) == 0 ==> result == 0; - ensures old(stake.value) == 0 ==> stake.value == old(stake.value); + ensures old(stake.value) == 0 ==> + stake.value == old(stake.value); } spec schema DistributeRewardsAbortsIf { @@ -578,15 +673,20 @@ spec supra_framework::stake { let stake_amount = coin::value(stake); let rewards_amount = if (stake_amount > 0) { - spec_rewards_amount(stake_amount, num_successful_proposals, num_total_proposals, rewards_rate, rewards_rate_denominator) - } else { - 0 - }; + spec_rewards_amount( + stake_amount, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ) + } else { 0 }; let amount = rewards_amount; let addr = type_info::type_of().account_address; aborts_if (rewards_amount > 0) && !exists>(addr); modifies global>(addr); - include (rewards_amount > 0) ==> coin::CoinAddAbortsIf { amount: amount }; + include (rewards_amount > 0) ==> + coin::CoinAddAbortsIf { amount: amount }; } spec get_reconfig_start_time_secs(): u64 { @@ -614,31 +714,39 @@ spec supra_framework::stake { requires rewards_rate_denominator > 0; requires rewards_rate <= rewards_rate_denominator; requires num_successful_proposals <= num_total_proposals; - ensures [concrete] (rewards_rate_denominator * num_total_proposals == 0) ==> result == 0; - ensures [concrete] (rewards_rate_denominator * num_total_proposals > 0) ==> { - let amount = ((stake_amount * rewards_rate * num_successful_proposals) / - (rewards_rate_denominator * num_total_proposals)); - result == amount - }; + ensures [concrete](rewards_rate_denominator * num_total_proposals == 0) ==> result == + 0; + ensures [concrete](rewards_rate_denominator * num_total_proposals > 0) ==> + { + let amount = + ((stake_amount * rewards_rate * num_successful_proposals) + / (rewards_rate_denominator * num_total_proposals)); + result == amount + }; aborts_if false; // Used an uninterpreted spec function to avoid dealing with the arithmetic overflow and non-linear arithmetic. - ensures [abstract] result == spec_rewards_amount( - stake_amount, - num_successful_proposals, - num_total_proposals, - rewards_rate, - rewards_rate_denominator); + ensures [abstract] result + == spec_rewards_amount( + stake_amount, + num_successful_proposals, + num_total_proposals, + rewards_rate, + rewards_rate_denominator + ); } spec find_validator { pragma opaque; aborts_if false; - ensures option::is_none(result) ==> (forall i in 0..len(v): v[i].addr != addr); - ensures option::is_some(result) ==> v[option::borrow(result)].addr == addr; + ensures option::is_none(result) ==> + (forall i in 0..len(v): v[i].addr != addr); + ensures option::is_some(result) ==> + v[option::borrow(result)].addr == addr; // Additional postcondition to help the quantifier instantiation. - ensures option::is_some(result) ==> spec_contains(v, addr); - ensures [abstract] result == spec_find_validator(v,addr); + ensures option::is_some(result) ==> + spec_contains(v, addr); + ensures [abstract] result == spec_find_validator(v, addr); } spec append { @@ -649,7 +757,10 @@ spec supra_framework::stake { // The prefix of the new `v1` is the same as the old `v1`. ensures (forall i in 0..old(len(v1)): v1[i] == old(v1[i])); // The suffix of the new `v1` is the same as the reverse of the old `v2`. - ensures (forall i in old(len(v1))..len(v1): v1[i] == old(v2[len(v2) - (i - len(v1)) - 1])); + ensures ( + forall i in old(len(v1))..len(v1): + v1[i] == old(v2[len(v2) - (i - len(v1)) - 1]) + ); } spec remove_validators { @@ -662,8 +773,8 @@ spec supra_framework::stake { let post post_pending_inactive_validators = post_validator_set.pending_inactive; invariant len(active_validators) > 0; - ensures len(active_validators) + len(pending_inactive_validators) == len(post_active_validators) - + len(post_pending_inactive_validators); + ensures len(active_validators) + len(pending_inactive_validators) + == len(post_active_validators) + len(post_pending_inactive_validators); } spec is_current_epoch_validator { @@ -675,14 +786,18 @@ spec supra_framework::stake { spec get_validator_state { aborts_if !exists(@supra_framework); let validator_set = global(@supra_framework); - ensures result == VALIDATOR_STATUS_PENDING_ACTIVE ==> spec_contains(validator_set.pending_active, pool_address); - ensures result == VALIDATOR_STATUS_ACTIVE ==> spec_contains(validator_set.active_validators, pool_address); - ensures result == VALIDATOR_STATUS_PENDING_INACTIVE ==> spec_contains(validator_set.pending_inactive, pool_address); - ensures result == VALIDATOR_STATUS_INACTIVE ==> ( - !spec_contains(validator_set.pending_active, pool_address) - && !spec_contains(validator_set.active_validators, pool_address) - && !spec_contains(validator_set.pending_inactive, pool_address) - ); + ensures result == VALIDATOR_STATUS_PENDING_ACTIVE ==> + spec_contains(validator_set.pending_active, pool_address); + ensures result == VALIDATOR_STATUS_ACTIVE ==> + spec_contains(validator_set.active_validators, pool_address); + ensures result == VALIDATOR_STATUS_PENDING_INACTIVE ==> + spec_contains(validator_set.pending_inactive, pool_address); + ensures result == VALIDATOR_STATUS_INACTIVE ==> + ( + !spec_contains(validator_set.pending_active, pool_address) + && !spec_contains(validator_set.active_validators, pool_address) + && !spec_contains(validator_set.pending_inactive, pool_address) + ); } spec add_stake_with_cap { @@ -705,22 +820,20 @@ spec supra_framework::stake { } spec initialize_stake_owner( - owner: &signer, - initial_stake_amount: u64, - operator: address, - voter: address, + owner: &signer, initial_stake_amount: u64, operator: address, voter: address ) { // TODO: These function failed in github CI pragma verify_duration_estimate = 120; include ResourceRequirement; let addr = signer::address_of(owner); - ensures global(addr) == ValidatorConfig { - consensus_pubkey: vector::empty(), - network_addresses: vector::empty(), - fullnode_addresses: vector::empty(), - validator_index: 0, - }; + ensures global(addr) + == ValidatorConfig { + consensus_pubkey: vector::empty(), + network_addresses: vector::empty(), + fullnode_addresses: vector::empty(), + validator_index: 0 + }; ensures global(addr) == OwnerCapability { pool_address: addr }; let post stakepool = global(addr); let post active = stakepool.active.value; @@ -740,8 +853,8 @@ spec supra_framework::stake { ensures if (table::spec_contains(fees_table, validator_addr)) { post_collected_fee.value == collected_fee.value + fee.value } else { - table::spec_contains(post_fees_table, validator_addr) && - table::spec_get(post_fees_table, validator_addr) == fee + table::spec_contains(post_fees_table, validator_addr) + && table::spec_get(post_fees_table, validator_addr) == fee }; } @@ -756,13 +869,19 @@ spec supra_framework::stake { let staking_config = global(aptos); let voting_power_increase_limit = staking_config.voting_power_increase_limit; aborts_if pre_validator_set.total_joining_power + increase_amount > MAX_U128; - aborts_if pre_validator_set.total_voting_power > 0 && pre_validator_set.total_voting_power * voting_power_increase_limit > MAX_U128; - aborts_if pre_validator_set.total_voting_power > 0 && - pre_validator_set.total_joining_power + increase_amount > pre_validator_set.total_voting_power * voting_power_increase_limit / 100; + aborts_if pre_validator_set.total_voting_power > 0 + && pre_validator_set.total_voting_power * voting_power_increase_limit + > MAX_U128; + aborts_if pre_validator_set.total_voting_power > 0 + && pre_validator_set.total_joining_power + increase_amount + > pre_validator_set.total_voting_power * voting_power_increase_limit + / 100; // Correctly modified total_joining_power and the value of total_voting_power is legal. ensures validator_set.total_voting_power > 0 ==> - validator_set.total_joining_power <= validator_set.total_voting_power * voting_power_increase_limit / 100; - ensures validator_set.total_joining_power == pre_validator_set.total_joining_power + increase_amount; + validator_set.total_joining_power + <= validator_set.total_voting_power * voting_power_increase_limit / 100; + ensures validator_set.total_joining_power + == pre_validator_set.total_joining_power + increase_amount; } spec assert_stake_pool_exists(pool_address: address) { @@ -781,13 +900,19 @@ spec supra_framework::stake { aborts_if !exists(owner); } - spec validator_consensus_infos_from_validator_set(validator_set: &ValidatorSet): vector { + spec validator_consensus_infos_from_validator_set(validator_set: &ValidatorSet): vector< + ValidatorConsensusInfo> { aborts_if false; - invariant spec_validator_indices_are_valid_config(validator_set.active_validators, - len(validator_set.active_validators) + len(validator_set.pending_inactive)); - invariant len(validator_set.pending_inactive) == 0 || - spec_validator_indices_are_valid_config(validator_set.pending_inactive, - len(validator_set.active_validators) + len(validator_set.pending_inactive)); + invariant spec_validator_indices_are_valid_config( + validator_set.active_validators, + len(validator_set.active_validators) + len(validator_set.pending_inactive) + ); + invariant len(validator_set.pending_inactive) == 0 + || spec_validator_indices_are_valid_config( + validator_set.pending_inactive, + len(validator_set.active_validators) + + len(validator_set.pending_inactive) + ); } // --------------------------------- @@ -805,23 +930,36 @@ spec supra_framework::stake { let validator_set = global(@supra_framework); let voting_power_increase_limit = config.voting_power_increase_limit; let post post_validator_set = global(@supra_framework); - let update_voting_power_increase = amount != 0 && (spec_contains(validator_set.active_validators, pool_address) - || spec_contains(validator_set.pending_active, pool_address)); - aborts_if update_voting_power_increase && validator_set.total_joining_power + amount > MAX_U128; - ensures update_voting_power_increase ==> post_validator_set.total_joining_power == validator_set.total_joining_power + amount; - aborts_if update_voting_power_increase && validator_set.total_voting_power > 0 - && validator_set.total_voting_power * voting_power_increase_limit > MAX_U128; - aborts_if update_voting_power_increase && validator_set.total_voting_power > 0 - && validator_set.total_joining_power + amount > validator_set.total_voting_power * voting_power_increase_limit / 100; + let update_voting_power_increase = amount != 0 + && ( + spec_contains(validator_set.active_validators, pool_address) + || spec_contains(validator_set.pending_active, pool_address) + ); + aborts_if update_voting_power_increase + && validator_set.total_joining_power + amount > MAX_U128; + ensures update_voting_power_increase ==> + post_validator_set.total_joining_power + == validator_set.total_joining_power + amount; + aborts_if update_voting_power_increase + && validator_set.total_voting_power > 0 + && validator_set.total_voting_power * voting_power_increase_limit + > MAX_U128; + aborts_if update_voting_power_increase + && validator_set.total_voting_power > 0 + && validator_set.total_joining_power + amount + > validator_set.total_voting_power * voting_power_increase_limit / 100; let stake_pool = global(pool_address); let post post_stake_pool = global(pool_address); let value_pending_active = stake_pool.pending_active.value; let value_active = stake_pool.active.value; - ensures amount != 0 && spec_is_current_epoch_validator(pool_address) ==> post_stake_pool.pending_active.value == value_pending_active + amount; - ensures amount != 0 && !spec_is_current_epoch_validator(pool_address) ==> post_stake_pool.active.value == value_active + amount; + ensures amount != 0 && spec_is_current_epoch_validator(pool_address) ==> + post_stake_pool.pending_active.value == value_pending_active + amount; + ensures amount != 0 && !spec_is_current_epoch_validator(pool_address) ==> + post_stake_pool.active.value == value_active + amount; let maximum_stake = config.maximum_stake; let value_pending_inactive = stake_pool.pending_inactive.value; - let next_epoch_voting_power = value_pending_active + value_active + value_pending_inactive; + let next_epoch_voting_power = value_pending_active + value_active + + value_pending_inactive; let voting_power = next_epoch_voting_power + amount; aborts_if amount != 0 && voting_power > MAX_U64; aborts_if amount != 0 && voting_power > maximum_stake; @@ -839,9 +977,8 @@ spec supra_framework::stake { } spec fun spec_is_allowed(account: address): bool { - if (!exists(@supra_framework)) { - true - } else { + if (!exists(@supra_framework)) { true } + else { let allowed = global(@supra_framework); contains(allowed.accounts, account) } @@ -852,35 +989,41 @@ spec supra_framework::stake { // A predicate that all given validators have been initialized. spec fun spec_validators_are_initialized(validators: vector): bool { forall i in 0..len(validators): - spec_has_stake_pool(validators[i].addr) && - spec_has_validator_config(validators[i].addr) + spec_has_stake_pool(validators[i].addr) + && spec_has_validator_config(validators[i].addr) } spec fun spec_validators_are_initialized_addrs(addrs: vector
): bool { forall i in 0..len(addrs): - spec_has_stake_pool(addrs[i]) && - spec_has_validator_config(addrs[i]) + spec_has_stake_pool(addrs[i]) && spec_has_validator_config(addrs[i]) } - // A predicate that the validator index of each given validator in-range. spec fun spec_validator_indices_are_valid(validators: vector): bool { - spec_validator_indices_are_valid_addr(validators, spec_validator_index_upper_bound()) && - spec_validator_indices_are_valid_config(validators, spec_validator_index_upper_bound()) + spec_validator_indices_are_valid_addr( + validators, spec_validator_index_upper_bound() + ) && spec_validator_indices_are_valid_config( + validators, spec_validator_index_upper_bound() + ) } - spec fun spec_validator_indices_are_valid_addr(validators: vector, upper_bound: u64): bool { + spec fun spec_validator_indices_are_valid_addr( + validators: vector, upper_bound: u64 + ): bool { forall i in 0..len(validators): global(validators[i].addr).validator_index < upper_bound } - spec fun spec_validator_indices_are_valid_config(validators: vector, upper_bound: u64): bool { + spec fun spec_validator_indices_are_valid_config( + validators: vector, upper_bound: u64 + ): bool { forall i in 0..len(validators): validators[i].config.validator_index < upper_bound } spec fun spec_validator_indices_active_pending_inactive(validator_set: ValidatorSet): bool { - len(validator_set.pending_inactive) + len(validator_set.active_validators) == spec_validator_index_upper_bound() + len(validator_set.pending_inactive) + len(validator_set.active_validators) + == spec_validator_index_upper_bound() } // The upper bound of validator indices. @@ -902,7 +1045,7 @@ spec supra_framework::stake { num_successful_proposals: u64, num_total_proposals: u64, rewards_rate: u64, - rewards_rate_denominator: u64, + rewards_rate_denominator: u64 ): u64; spec fun spec_contains(validators: vector, addr: address): bool { @@ -912,8 +1055,10 @@ spec supra_framework::stake { spec fun spec_is_current_epoch_validator(pool_address: address): bool { let validator_set = global(@supra_framework); !spec_contains(validator_set.pending_active, pool_address) - && (spec_contains(validator_set.active_validators, pool_address) - || spec_contains(validator_set.pending_inactive, pool_address)) + && ( + spec_contains(validator_set.active_validators, pool_address) + || spec_contains(validator_set.pending_inactive, pool_address) + ) } // These resources are required to successfully execute `on_new_epoch`, which cannot @@ -923,7 +1068,8 @@ spec supra_framework::stake { requires exists(@supra_framework); requires exists(@supra_framework); requires exists(@supra_framework); - requires exists(@supra_framework) || !features::spec_periodical_reward_rate_decrease_enabled(); + requires exists(@supra_framework) + || !features::spec_periodical_reward_rate_decrease_enabled(); requires exists(@supra_framework); requires exists(@supra_framework); } @@ -932,31 +1078,40 @@ spec supra_framework::stake { // So we write two helper functions here to model function staking_config::get_reward_rate(). spec fun spec_get_reward_rate_1(config: StakingConfig): num { if (features::spec_periodical_reward_rate_decrease_enabled()) { - let epoch_rewards_rate = global(@supra_framework).rewards_rate; - if (epoch_rewards_rate.value == 0) { - 0 - } else { - let denominator_0 = aptos_std::fixed_point64::spec_divide_u128(staking_config::MAX_REWARDS_RATE, epoch_rewards_rate); + let epoch_rewards_rate = + global(@supra_framework).rewards_rate; + if (epoch_rewards_rate.value == 0) { 0 } + else { + let denominator_0 = + aptos_std::fixed_point64::spec_divide_u128( + staking_config::MAX_REWARDS_RATE, epoch_rewards_rate + ); let denominator = if (denominator_0 > MAX_U64) { MAX_U64 } else { denominator_0 }; - let nominator = aptos_std::fixed_point64::spec_multiply_u128(denominator, epoch_rewards_rate); + let nominator = + aptos_std::fixed_point64::spec_multiply_u128( + denominator, epoch_rewards_rate + ); nominator } } else { - config.rewards_rate + config.rewards_rate } } spec fun spec_get_reward_rate_2(config: StakingConfig): num { if (features::spec_periodical_reward_rate_decrease_enabled()) { - let epoch_rewards_rate = global(@supra_framework).rewards_rate; - if (epoch_rewards_rate.value == 0) { - 1 - } else { - let denominator_0 = aptos_std::fixed_point64::spec_divide_u128(staking_config::MAX_REWARDS_RATE, epoch_rewards_rate); + let epoch_rewards_rate = + global(@supra_framework).rewards_rate; + if (epoch_rewards_rate.value == 0) { 1 } + else { + let denominator_0 = + aptos_std::fixed_point64::spec_divide_u128( + staking_config::MAX_REWARDS_RATE, epoch_rewards_rate + ); let denominator = if (denominator_0 > MAX_U64) { MAX_U64 } else { @@ -965,7 +1120,7 @@ spec supra_framework::stake { denominator } } else { - config.rewards_rate_denominator + config.rewards_rate_denominator } } } diff --git a/aptos-move/framework/supra-framework/sources/staking_contract.move b/aptos-move/framework/supra-framework/sources/staking_contract.move index ec25f5c000bf0..78f99527d6930 100644 --- a/aptos-move/framework/supra-framework/sources/staking_contract.move +++ b/aptos-move/framework/supra-framework/sources/staking_contract.move @@ -80,7 +80,7 @@ module supra_framework::staking_contract { // Current distributions, including operator commission withdrawals and staker's partial withdrawals. distribution_pool: Pool, // Just in case we need the SignerCap for stake pool account in the future. - signer_cap: SignerCapability, + signer_cap: SignerCapability } struct Store has key { @@ -95,18 +95,18 @@ module supra_framework::staking_contract { unlock_stake_events: EventHandle, switch_operator_events: EventHandle, add_distribution_events: EventHandle, - distribute_events: EventHandle, + distribute_events: EventHandle } struct BeneficiaryForOperator has key { - beneficiary_for_operator: address, + beneficiary_for_operator: address } struct UpdateCommissionEvent has drop, store { staker: address, operator: address, old_commission_percentage: u64, - new_commission_percentage: u64, + new_commission_percentage: u64 } #[event] @@ -114,12 +114,14 @@ module supra_framework::staking_contract { staker: address, operator: address, old_commission_percentage: u64, - new_commission_percentage: u64, + new_commission_percentage: u64 } - #[resource_group_member(group = supra_framework::staking_contract::StakingGroupContainer)] + #[resource_group_member( + group = supra_framework::staking_contract::StakingGroupContainer + )] struct StakingGroupUpdateCommissionEvent has key { - update_commission_events: EventHandle, + update_commission_events: EventHandle } #[event] @@ -128,7 +130,7 @@ module supra_framework::staking_contract { voter: address, pool_address: address, principal: u64, - commission_percentage: u64, + commission_percentage: u64 } #[event] @@ -136,13 +138,13 @@ module supra_framework::staking_contract { operator: address, pool_address: address, old_voter: address, - new_voter: address, + new_voter: address } #[event] struct ResetLockup has drop, store { operator: address, - pool_address: address, + pool_address: address } #[event] @@ -157,7 +159,7 @@ module supra_framework::staking_contract { operator: address, pool_address: address, accumulated_rewards: u64, - commission_amount: u64, + commission_amount: u64 } #[event] @@ -165,21 +167,21 @@ module supra_framework::staking_contract { operator: address, pool_address: address, amount: u64, - commission_paid: u64, + commission_paid: u64 } #[event] struct SwitchOperator has drop, store { old_operator: address, new_operator: address, - pool_address: address, + pool_address: address } #[event] struct AddDistribution has drop, store { operator: address, pool_address: address, - amount: u64, + amount: u64 } #[event] @@ -187,14 +189,14 @@ module supra_framework::staking_contract { operator: address, pool_address: address, recipient: address, - amount: u64, + amount: u64 } #[event] struct SetBeneficiaryForOperator has drop, store { operator: address, old_beneficiary: address, - new_beneficiary: address, + new_beneficiary: address } struct CreateStakingContractEvent has drop, store { @@ -202,19 +204,19 @@ module supra_framework::staking_contract { voter: address, pool_address: address, principal: u64, - commission_percentage: u64, + commission_percentage: u64 } struct UpdateVoterEvent has drop, store { operator: address, pool_address: address, old_voter: address, - new_voter: address, + new_voter: address } struct ResetLockupEvent has drop, store { operator: address, - pool_address: address, + pool_address: address } struct AddStakeEvent has drop, store { @@ -227,33 +229,33 @@ module supra_framework::staking_contract { operator: address, pool_address: address, accumulated_rewards: u64, - commission_amount: u64, + commission_amount: u64 } struct UnlockStakeEvent has drop, store { operator: address, pool_address: address, amount: u64, - commission_paid: u64, + commission_paid: u64 } struct SwitchOperatorEvent has drop, store { old_operator: address, new_operator: address, - pool_address: address, + pool_address: address } struct AddDistributionEvent has drop, store { operator: address, pool_address: address, - amount: u64, + amount: u64 } struct DistributeEvent has drop, store { operator: address, pool_address: address, recipient: address, - amount: u64, + amount: u64 } #[view] @@ -296,7 +298,9 @@ module supra_framework::staking_contract { /// 3. The commission amount owned from those accumulated rewards. /// /// This errors out the staking contract with the provided staker and operator doesn't exist. - public fun staking_contract_amounts(staker: address, operator: address): (u64, u64, u64) acquires Store { + public fun staking_contract_amounts( + staker: address, operator: address + ): (u64, u64, u64) acquires Store { assert_staking_contract_exists(staker, operator); let staking_contracts = &borrow_global(staker).staking_contracts; let staking_contract = simple_map::borrow(staking_contracts, &operator); @@ -307,10 +311,14 @@ module supra_framework::staking_contract { /// Return the number of pending distributions (e.g. commission, withdrawals from stakers). /// /// This errors out the staking contract with the provided staker and operator doesn't exist. - public fun pending_distribution_counts(staker: address, operator: address): u64 acquires Store { + public fun pending_distribution_counts( + staker: address, operator: address + ): u64 acquires Store { assert_staking_contract_exists(staker, operator); let staking_contracts = &borrow_global(staker).staking_contracts; - pool_u64::shareholders_count(&simple_map::borrow(staking_contracts, &operator).distribution_pool) + pool_u64::shareholders_count( + &simple_map::borrow(staking_contracts, &operator).distribution_pool + ) } #[view] @@ -339,7 +347,7 @@ module supra_framework::staking_contract { public fun get_expected_stake_pool_address( staker: address, operator: address, - contract_creation_seed: vector, + contract_creation_seed: vector ): address { let seed = create_resource_account_seed(staker, operator, contract_creation_seed); account::create_resource_address(&staker, seed) @@ -353,11 +361,17 @@ module supra_framework::staking_contract { amount: u64, commission_percentage: u64, // Optional seed used when creating the staking contract account. - contract_creation_seed: vector, + contract_creation_seed: vector ) acquires Store { let staked_coins = coin::withdraw(staker, amount); create_staking_contract_with_coins( - staker, operator, voter, staked_coins, commission_percentage, contract_creation_seed); + staker, + operator, + voter, + staked_coins, + commission_percentage, + contract_creation_seed + ); } /// Staker can call this function to create a simple staking contract with a specified operator. @@ -368,17 +382,21 @@ module supra_framework::staking_contract { coins: Coin, commission_percentage: u64, // Optional seed used when creating the staking contract account. - contract_creation_seed: vector, + contract_creation_seed: vector ): address acquires Store { assert!( commission_percentage >= 0 && commission_percentage <= 100, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE), + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE) ); // The amount should be at least the min_stake_required, so the stake pool will be eligible to join the // validator set. - let (min_stake_required, _) = staking_config::get_required_stake(&staking_config::get()); + let (min_stake_required, _) = + staking_config::get_required_stake(&staking_config::get()); let principal = coin::value(&coins); - assert!(principal >= min_stake_required, error::invalid_argument(EINSUFFICIENT_STAKE_AMOUNT)); + assert!( + principal >= min_stake_required, + error::invalid_argument(EINSUFFICIENT_STAKE_AMOUNT) + ); // Initialize Store resource if this is the first time the staker has delegated to anyone. let staker_address = signer::address_of(staker); @@ -404,35 +422,56 @@ module supra_framework::staking_contract { // Create the contract record. let pool_address = signer::address_of(&stake_pool_signer); - simple_map::add(staking_contracts, operator, StakingContract { - principal, - pool_address, - owner_cap, - commission_percentage, - // Make sure we don't have too many pending recipients in the distribution pool. - // Otherwise, a griefing attack is possible where the staker can keep switching operators and create too - // many pending distributions. This can lead to out-of-gas failure whenever distribute() is called. - distribution_pool: pool_u64::create(MAXIMUM_PENDING_DISTRIBUTIONS), - signer_cap: stake_pool_signer_cap, - }); + simple_map::add( + staking_contracts, + operator, + StakingContract { + principal, + pool_address, + owner_cap, + commission_percentage, + // Make sure we don't have too many pending recipients in the distribution pool. + // Otherwise, a griefing attack is possible where the staker can keep switching operators and create too + // many pending distributions. This can lead to out-of-gas failure whenever distribute() is called. + distribution_pool: pool_u64::create(MAXIMUM_PENDING_DISTRIBUTIONS), + signer_cap: stake_pool_signer_cap + } + ); if (std::features::module_event_migration_enabled()) { - emit(CreateStakingContract { operator, voter, pool_address, principal, commission_percentage }); + emit( + CreateStakingContract { + operator, + voter, + pool_address, + principal, + commission_percentage + } + ); }; emit_event( &mut store.create_staking_contract_events, - CreateStakingContractEvent { operator, voter, pool_address, principal, commission_percentage }, + CreateStakingContractEvent { + operator, + voter, + pool_address, + principal, + commission_percentage + } ); pool_address } /// Add more stake to an existing staking contract. - public entry fun add_stake(staker: &signer, operator: address, amount: u64) acquires Store { + public entry fun add_stake( + staker: &signer, operator: address, amount: u64 + ) acquires Store { let staker_address = signer::address_of(staker); assert_staking_contract_exists(staker_address, operator); let store = borrow_global_mut(staker_address); - let staking_contract = simple_map::borrow_mut(&mut store.staking_contracts, &operator); + let staking_contract = + simple_map::borrow_mut(&mut store.staking_contracts, &operator); // Add the stake to the stake pool. let staked_coins = coin::withdraw(staker, amount); @@ -445,17 +484,20 @@ module supra_framework::staking_contract { }; emit_event( &mut store.add_stake_events, - AddStakeEvent { operator, pool_address, amount }, + AddStakeEvent { operator, pool_address, amount } ); } /// Convenient function to allow the staker to update the voter address in a staking contract they made. - public entry fun update_voter(staker: &signer, operator: address, new_voter: address) acquires Store { + public entry fun update_voter( + staker: &signer, operator: address, new_voter: address + ) acquires Store { let staker_address = signer::address_of(staker); assert_staking_contract_exists(staker_address, operator); let store = borrow_global_mut(staker_address); - let staking_contract = simple_map::borrow_mut(&mut store.staking_contracts, &operator); + let staking_contract = + simple_map::borrow_mut(&mut store.staking_contracts, &operator); let pool_address = staking_contract.pool_address; let old_voter = stake::get_delegated_voter(pool_address); stake::set_delegated_voter_with_cap(&staking_contract.owner_cap, new_voter); @@ -465,7 +507,7 @@ module supra_framework::staking_contract { }; emit_event( &mut store.update_voter_events, - UpdateVoterEvent { operator, pool_address, old_voter, new_voter }, + UpdateVoterEvent { operator, pool_address, old_voter, new_voter } ); } @@ -476,39 +518,49 @@ module supra_framework::staking_contract { assert_staking_contract_exists(staker_address, operator); let store = borrow_global_mut(staker_address); - let staking_contract = simple_map::borrow_mut(&mut store.staking_contracts, &operator); + let staking_contract = + simple_map::borrow_mut(&mut store.staking_contracts, &operator); let pool_address = staking_contract.pool_address; stake::increase_lockup_with_cap(&staking_contract.owner_cap); if (std::features::module_event_migration_enabled()) { emit(ResetLockup { operator, pool_address }); }; - emit_event(&mut store.reset_lockup_events, ResetLockupEvent { operator, pool_address }); + emit_event( + &mut store.reset_lockup_events, ResetLockupEvent { operator, pool_address } + ); } /// Convenience function to allow a staker to update the commission percentage paid to the operator. /// TODO: fix the typo in function name. commision -> commission public entry fun update_commision( - staker: &signer, - operator: address, - new_commission_percentage: u64 + staker: &signer, operator: address, new_commission_percentage: u64 ) acquires Store, BeneficiaryForOperator, StakingGroupUpdateCommissionEvent { assert!( new_commission_percentage >= 0 && new_commission_percentage <= 100, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE), + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE) ); let staker_address = signer::address_of(staker); - assert!(exists(staker_address), error::not_found(ENO_STAKING_CONTRACT_FOUND_FOR_STAKER)); + assert!( + exists(staker_address), + error::not_found(ENO_STAKING_CONTRACT_FOUND_FOR_STAKER) + ); let store = borrow_global_mut(staker_address); - let staking_contract = simple_map::borrow_mut(&mut store.staking_contracts, &operator); - distribute_internal(staker_address, operator, staking_contract, &mut store.distribute_events); + let staking_contract = + simple_map::borrow_mut(&mut store.staking_contracts, &operator); + distribute_internal( + staker_address, + operator, + staking_contract, + &mut store.distribute_events + ); request_commission_internal( operator, staking_contract, &mut store.add_distribution_events, - &mut store.request_commission_events, + &mut store.request_commission_events ); let old_commission_percentage = staking_contract.commission_percentage; staking_contract.commission_percentage = new_commission_percentage; @@ -516,20 +568,29 @@ module supra_framework::staking_contract { move_to( staker, StakingGroupUpdateCommissionEvent { - update_commission_events: account::new_event_handle( - staker - ) + update_commission_events: account::new_event_handle< + UpdateCommissionEvent>(staker) } ) }; if (std::features::module_event_migration_enabled()) { emit( - UpdateCommission { staker: staker_address, operator, old_commission_percentage, new_commission_percentage } + UpdateCommission { + staker: staker_address, + operator, + old_commission_percentage, + new_commission_percentage + } ); }; emit_event( &mut borrow_global_mut(staker_address).update_commission_events, - UpdateCommissionEvent { staker: staker_address, operator, old_commission_percentage, new_commission_percentage } + UpdateCommissionEvent { + staker: staker_address, + operator, + old_commission_percentage, + new_commission_percentage + } ); } @@ -538,32 +599,33 @@ module supra_framework::staking_contract { /// /// Only staker, operator or beneficiary can call this. public entry fun request_commission( - account: &signer, - staker: address, - operator: address + account: &signer, staker: address, operator: address ) acquires Store, BeneficiaryForOperator { let account_addr = signer::address_of(account); assert!( - account_addr == staker || account_addr == operator || account_addr == beneficiary_for_operator(operator), + account_addr == staker + || account_addr == operator + || account_addr == beneficiary_for_operator(operator), error::unauthenticated(ENOT_STAKER_OR_OPERATOR_OR_BENEFICIARY) ); assert_staking_contract_exists(staker, operator); let store = borrow_global_mut(staker); - let staking_contract = simple_map::borrow_mut(&mut store.staking_contracts, &operator); + let staking_contract = + simple_map::borrow_mut(&mut store.staking_contracts, &operator); // Short-circuit if zero commission. - if (staking_contract.commission_percentage == 0) { - return - }; + if (staking_contract.commission_percentage == 0) { return }; // Force distribution of any already inactive stake. - distribute_internal(staker, operator, staking_contract, &mut store.distribute_events); + distribute_internal( + staker, operator, staking_contract, &mut store.distribute_events + ); request_commission_internal( operator, staking_contract, &mut store.add_distribution_events, - &mut store.request_commission_events, + &mut store.request_commission_events ); } @@ -571,7 +633,7 @@ module supra_framework::staking_contract { operator: address, staking_contract: &mut StakingContract, add_distribution_events: &mut EventHandle, - request_commission_events: &mut EventHandle, + request_commission_events: &mut EventHandle ): u64 { // Unlock just the commission portion from the stake pool. let (total_active_stake, accumulated_rewards, commission_amount) = @@ -584,7 +646,13 @@ module supra_framework::staking_contract { }; // Add a distribution for the operator. - add_distribution(operator, staking_contract, operator, commission_amount, add_distribution_events); + add_distribution( + operator, + staking_contract, + operator, + commission_amount, + add_distribution_events + ); // Request to unlock the commission from the stake pool. // This won't become fully unlocked until the stake pool's lockup expires. @@ -592,11 +660,23 @@ module supra_framework::staking_contract { let pool_address = staking_contract.pool_address; if (std::features::module_event_migration_enabled()) { - emit(RequestCommission { operator, pool_address, accumulated_rewards, commission_amount }); + emit( + RequestCommission { + operator, + pool_address, + accumulated_rewards, + commission_amount + } + ); }; emit_event( request_commission_events, - RequestCommissionEvent { operator, pool_address, accumulated_rewards, commission_amount }, + RequestCommissionEvent { + operator, + pool_address, + accumulated_rewards, + commission_amount + } ); commission_amount @@ -605,9 +685,7 @@ module supra_framework::staking_contract { /// Staker can call this to request withdrawal of part or all of their staking_contract. /// This also triggers paying commission to the operator for accounting simplicity. public entry fun unlock_stake( - staker: &signer, - operator: address, - amount: u64 + staker: &signer, operator: address, amount: u64 ) acquires Store, BeneficiaryForOperator { // Short-circuit if amount is 0. if (amount == 0) return; @@ -616,20 +694,27 @@ module supra_framework::staking_contract { assert_staking_contract_exists(staker_address, operator); let store = borrow_global_mut(staker_address); - let staking_contract = simple_map::borrow_mut(&mut store.staking_contracts, &operator); + let staking_contract = + simple_map::borrow_mut(&mut store.staking_contracts, &operator); // Force distribution of any already inactive stake. - distribute_internal(staker_address, operator, staking_contract, &mut store.distribute_events); - - // For simplicity, we request commission to be paid out first. This avoids having to ensure to staker doesn't - // withdraw into the commission portion. - let commission_paid = request_commission_internal( + distribute_internal( + staker_address, operator, staking_contract, - &mut store.add_distribution_events, - &mut store.request_commission_events, + &mut store.distribute_events ); + // For simplicity, we request commission to be paid out first. This avoids having to ensure to staker doesn't + // withdraw into the commission portion. + let commission_paid = + request_commission_internal( + operator, + staking_contract, + &mut store.add_distribution_events, + &mut store.request_commission_events + ); + // If there's less active stake remaining than the amount requested (potentially due to commission), // only withdraw up to the active amount. let (active, _, _, _) = stake::get_stake(staking_contract.pool_address); @@ -639,7 +724,13 @@ module supra_framework::staking_contract { staking_contract.principal = staking_contract.principal - amount; // Record a distribution for the staker. - add_distribution(operator, staking_contract, staker_address, amount, &mut store.add_distribution_events); + add_distribution( + operator, + staking_contract, + staker_address, + amount, + &mut store.add_distribution_events + ); // Request to unlock the distribution amount from the stake pool. // This won't become fully unlocked until the stake pool's lockup expires. @@ -651,17 +742,20 @@ module supra_framework::staking_contract { }; emit_event( &mut store.unlock_stake_events, - UnlockStakeEvent { pool_address, operator, amount, commission_paid }, + UnlockStakeEvent { pool_address, operator, amount, commission_paid } ); } /// Unlock all accumulated rewards since the last recorded principals. - public entry fun unlock_rewards(staker: &signer, operator: address) acquires Store, BeneficiaryForOperator { + public entry fun unlock_rewards( + staker: &signer, operator: address + ) acquires Store, BeneficiaryForOperator { let staker_address = signer::address_of(staker); assert_staking_contract_exists(staker_address, operator); // Calculate how much rewards belongs to the staker after commission is paid. - let (_, accumulated_rewards, unpaid_commission) = staking_contract_amounts(staker_address, operator); + let (_, accumulated_rewards, unpaid_commission) = + staking_contract_amounts(staker_address, operator); let staker_rewards = accumulated_rewards - unpaid_commission; unlock_stake(staker, operator, staker_rewards); } @@ -670,7 +764,7 @@ module supra_framework::staking_contract { public entry fun switch_operator_with_same_commission( staker: &signer, old_operator: address, - new_operator: address, + new_operator: address ) acquires Store, BeneficiaryForOperator { let staker_address = signer::address_of(staker); assert_staking_contract_exists(staker_address, old_operator); @@ -684,7 +778,7 @@ module supra_framework::staking_contract { staker: &signer, old_operator: address, new_operator: address, - new_commission_percentage: u64, + new_commission_percentage: u64 ) acquires Store, BeneficiaryForOperator { let staker_address = signer::address_of(staker); assert_staking_contract_exists(staker_address, old_operator); @@ -694,12 +788,17 @@ module supra_framework::staking_contract { let staking_contracts = &mut store.staking_contracts; assert!( !simple_map::contains_key(staking_contracts, &new_operator), - error::invalid_state(ECANT_MERGE_STAKING_CONTRACTS), + error::invalid_state(ECANT_MERGE_STAKING_CONTRACTS) ); let (_, staking_contract) = simple_map::remove(staking_contracts, &old_operator); // Force distribution of any already inactive stake. - distribute_internal(staker_address, old_operator, &mut staking_contract, &mut store.distribute_events); + distribute_internal( + staker_address, + old_operator, + &mut staking_contract, + &mut store.distribute_events + ); // For simplicity, we request commission to be paid out first. This avoids having to ensure to staker doesn't // withdraw into the commission portion. @@ -707,7 +806,7 @@ module supra_framework::staking_contract { old_operator, &mut staking_contract, &mut store.add_distribution_events, - &mut store.request_commission_events, + &mut store.request_commission_events ); // Update the staking contract's commission rate and stake pool's operator. @@ -729,36 +828,47 @@ module supra_framework::staking_contract { /// beneficiary. To ensures payment to the current beneficiary, one should first call `distribute` before switching /// the beneficiary. An operator can set one beneficiary for staking contract pools, not a separate one for each pool. public entry fun set_beneficiary_for_operator( - operator: &signer, - new_beneficiary: address + operator: &signer, new_beneficiary: address ) acquires BeneficiaryForOperator { - assert!(features::operator_beneficiary_change_enabled(), std::error::invalid_state( - EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED - )); + assert!( + features::operator_beneficiary_change_enabled(), + std::error::invalid_state(EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED) + ); // The beneficiay address of an operator is stored under the operator's address. // So, the operator does not need to be validated with respect to a staking pool. let operator_addr = signer::address_of(operator); let old_beneficiary = beneficiary_for_operator(operator_addr); if (exists(operator_addr)) { - borrow_global_mut(operator_addr).beneficiary_for_operator = new_beneficiary; + borrow_global_mut(operator_addr).beneficiary_for_operator = + new_beneficiary; } else { - move_to(operator, BeneficiaryForOperator { beneficiary_for_operator: new_beneficiary }); + move_to( + operator, + BeneficiaryForOperator { beneficiary_for_operator: new_beneficiary } + ); }; - emit(SetBeneficiaryForOperator { - operator: operator_addr, - old_beneficiary, - new_beneficiary, - }); + emit( + SetBeneficiaryForOperator { + operator: operator_addr, + old_beneficiary, + new_beneficiary + } + ); } /// Allow anyone to distribute already unlocked funds. This does not affect reward compounding and therefore does /// not need to be restricted to just the staker or operator. - public entry fun distribute(staker: address, operator: address) acquires Store, BeneficiaryForOperator { + public entry fun distribute( + staker: address, operator: address + ) acquires Store, BeneficiaryForOperator { assert_staking_contract_exists(staker, operator); let store = borrow_global_mut(staker); - let staking_contract = simple_map::borrow_mut(&mut store.staking_contracts, &operator); - distribute_internal(staker, operator, staking_contract, &mut store.distribute_events); + let staking_contract = + simple_map::borrow_mut(&mut store.staking_contracts, &operator); + distribute_internal( + staker, operator, staking_contract, &mut store.distribute_events + ); } /// Distribute all unlocked (inactive) funds according to distribution shares. @@ -766,12 +876,15 @@ module supra_framework::staking_contract { staker: address, operator: address, staking_contract: &mut StakingContract, - distribute_events: &mut EventHandle, + distribute_events: &mut EventHandle ) acquires BeneficiaryForOperator { let pool_address = staking_contract.pool_address; let (_, inactive, _, pending_inactive) = stake::get_stake(pool_address); let total_potential_withdrawable = inactive + pending_inactive; - let coins = stake::withdraw_with_cap(&staking_contract.owner_cap, total_potential_withdrawable); + let coins = + stake::withdraw_with_cap( + &staking_contract.owner_cap, total_potential_withdrawable + ); let distribution_amount = coin::value(&coins); if (distribution_amount == 0) { coin::destroy_zero(coins); @@ -780,26 +893,45 @@ module supra_framework::staking_contract { let distribution_pool = &mut staking_contract.distribution_pool; update_distribution_pool( - distribution_pool, distribution_amount, operator, staking_contract.commission_percentage); + distribution_pool, + distribution_amount, + operator, + staking_contract.commission_percentage + ); // Buy all recipients out of the distribution pool. while (pool_u64::shareholders_count(distribution_pool) > 0) { let recipients = pool_u64::shareholders(distribution_pool); let recipient = *vector::borrow(&mut recipients, 0); let current_shares = pool_u64::shares(distribution_pool, recipient); - let amount_to_distribute = pool_u64::redeem_shares(distribution_pool, recipient, current_shares); + let amount_to_distribute = + pool_u64::redeem_shares(distribution_pool, recipient, current_shares); // If the recipient is the operator, send the commission to the beneficiary instead. if (recipient == operator) { recipient = beneficiary_for_operator(operator); }; - supra_account::deposit_coins(recipient, coin::extract(&mut coins, amount_to_distribute)); + supra_account::deposit_coins( + recipient, coin::extract(&mut coins, amount_to_distribute) + ); if (std::features::module_event_migration_enabled()) { - emit(Distribute { operator, pool_address, recipient, amount: amount_to_distribute }); + emit( + Distribute { + operator, + pool_address, + recipient, + amount: amount_to_distribute + } + ); }; emit_event( distribute_events, - DistributeEvent { operator, pool_address, recipient, amount: amount_to_distribute } + DistributeEvent { + operator, + pool_address, + recipient, + amount: amount_to_distribute + } ); }; @@ -813,12 +945,16 @@ module supra_framework::staking_contract { } /// Assert that a staking_contract exists for the staker/operator pair. - fun assert_staking_contract_exists(staker: address, operator: address) acquires Store { - assert!(exists(staker), error::not_found(ENO_STAKING_CONTRACT_FOUND_FOR_STAKER)); + fun assert_staking_contract_exists( + staker: address, operator: address + ) acquires Store { + assert!( + exists(staker), error::not_found(ENO_STAKING_CONTRACT_FOUND_FOR_STAKER) + ); let staking_contracts = &mut borrow_global_mut(staker).staking_contracts; assert!( simple_map::contains_key(staking_contracts, &operator), - error::not_found(ENO_STAKING_CONTRACT_FOUND_FOR_OPERATOR), + error::not_found(ENO_STAKING_CONTRACT_FOUND_FOR_OPERATOR) ); } @@ -831,9 +967,14 @@ module supra_framework::staking_contract { add_distribution_events: &mut EventHandle ) { let distribution_pool = &mut staking_contract.distribution_pool; - let (_, _, _, total_distribution_amount) = stake::get_stake(staking_contract.pool_address); + let (_, _, _, total_distribution_amount) = + stake::get_stake(staking_contract.pool_address); update_distribution_pool( - distribution_pool, total_distribution_amount, operator, staking_contract.commission_percentage); + distribution_pool, + total_distribution_amount, + operator, + staking_contract.commission_percentage + ); pool_u64::buy_in(distribution_pool, recipient, coins_amount); let pool_address = staking_contract.pool_address; @@ -847,15 +988,19 @@ module supra_framework::staking_contract { } /// Calculate accumulated rewards and commissions since last update. - fun get_staking_contract_amounts_internal(staking_contract: &StakingContract): (u64, u64, u64) { + fun get_staking_contract_amounts_internal( + staking_contract: &StakingContract + ): (u64, u64, u64) { // Pending_inactive is not included in the calculation because pending_inactive can only come from: // 1. Outgoing commissions. This means commission has already been extracted. // 2. Stake withdrawals from stakers. This also means commission has already been extracted as // request_commission_internal is called in unlock_stake - let (active, _, pending_active, _) = stake::get_stake(staking_contract.pool_address); + let (active, _, pending_active, _) = + stake::get_stake(staking_contract.pool_address); let total_active_stake = active + pending_active; let accumulated_rewards = total_active_stake - staking_contract.principal; - let commission_amount = accumulated_rewards * staking_contract.commission_percentage / 100; + let commission_amount = + accumulated_rewards * staking_contract.commission_percentage / 100; (total_active_stake, accumulated_rewards, commission_amount) } @@ -864,13 +1009,16 @@ module supra_framework::staking_contract { staker: &signer, operator: address, voter: address, - contract_creation_seed: vector, + contract_creation_seed: vector ): (signer, SignerCapability, OwnerCapability) { // Generate a seed that will be used to create the resource account that hosts the staking contract. - let seed = create_resource_account_seed( - signer::address_of(staker), operator, contract_creation_seed); + let seed = + create_resource_account_seed( + signer::address_of(staker), operator, contract_creation_seed + ); - let (stake_pool_signer, stake_pool_signer_cap) = account::create_resource_account(staker, seed); + let (stake_pool_signer, stake_pool_signer_cap) = + account::create_resource_account(staker, seed); stake::initialize_stake_owner(&stake_pool_signer, 0, operator, voter); // Extract owner_cap from the StakePool, so we have control over it in the staking_contracts flow. @@ -885,31 +1033,39 @@ module supra_framework::staking_contract { distribution_pool: &mut Pool, updated_total_coins: u64, operator: address, - commission_percentage: u64, + commission_percentage: u64 ) { // Short-circuit and do nothing if the pool's total value has not changed. - if (pool_u64::total_coins(distribution_pool) == updated_total_coins) { - return - }; + if (pool_u64::total_coins(distribution_pool) == updated_total_coins) { return }; // Charge all stakeholders (except for the operator themselves) commission on any rewards earnt relatively to the // previous value of the distribution pool. let shareholders = &pool_u64::shareholders(distribution_pool); - vector::for_each_ref(shareholders, |shareholder| { - let shareholder: address = *shareholder; - if (shareholder != operator) { - let shares = pool_u64::shares(distribution_pool, shareholder); - let previous_worth = pool_u64::balance(distribution_pool, shareholder); - let current_worth = pool_u64::shares_to_amount_with_total_coins( - distribution_pool, shares, updated_total_coins); - let unpaid_commission = (current_worth - previous_worth) * commission_percentage / 100; - // Transfer shares from current shareholder to the operator as payment. - // The value of the shares should use the updated pool's total value. - let shares_to_transfer = pool_u64::amount_to_shares_with_total_coins( - distribution_pool, unpaid_commission, updated_total_coins); - pool_u64::transfer_shares(distribution_pool, shareholder, operator, shares_to_transfer); - }; - }); + vector::for_each_ref( + shareholders, + |shareholder| { + let shareholder: address = *shareholder; + if (shareholder != operator) { + let shares = pool_u64::shares(distribution_pool, shareholder); + let previous_worth = pool_u64::balance(distribution_pool, shareholder); + let current_worth = + pool_u64::shares_to_amount_with_total_coins( + distribution_pool, shares, updated_total_coins + ); + let unpaid_commission = + (current_worth - previous_worth) * commission_percentage / 100; + // Transfer shares from current shareholder to the operator as payment. + // The value of the shares should use the updated pool's total value. + let shares_to_transfer = + pool_u64::amount_to_shares_with_total_coins( + distribution_pool, unpaid_commission, updated_total_coins + ); + pool_u64::transfer_shares( + distribution_pool, shareholder, operator, shares_to_transfer + ); + }; + } + ); pool_u64::update_total_coins(distribution_pool, updated_total_coins); } @@ -918,7 +1074,7 @@ module supra_framework::staking_contract { fun create_resource_account_seed( staker: address, operator: address, - contract_creation_seed: vector, + contract_creation_seed: vector ): vector { let seed = bcs::to_bytes(&staker); vector::append(&mut seed, bcs::to_bytes(&operator)); @@ -935,15 +1091,20 @@ module supra_framework::staking_contract { Store { staking_contracts: simple_map::create(), // Events. - create_staking_contract_events: account::new_event_handle(staker), + create_staking_contract_events: account::new_event_handle< + CreateStakingContractEvent>(staker), update_voter_events: account::new_event_handle(staker), reset_lockup_events: account::new_event_handle(staker), add_stake_events: account::new_event_handle(staker), - request_commission_events: account::new_event_handle(staker), + request_commission_events: account::new_event_handle( + staker + ), unlock_stake_events: account::new_event_handle(staker), switch_operator_events: account::new_event_handle(staker), - add_distribution_events: account::new_event_handle(staker), - distribute_events: account::new_event_handle(staker), + add_distribution_events: account::new_event_handle( + staker + ), + distribute_events: account::new_event_handle(staker) } } @@ -968,7 +1129,12 @@ module supra_framework::staking_contract { const OPERATOR_BENEFICIARY_CHANGE: u64 = 39; #[test_only] - public fun setup(supra_framework: &signer, staker: &signer, operator: &signer, initial_balance: u64) { + public fun setup( + supra_framework: &signer, + staker: &signer, + operator: &signer, + initial_balance: u64 + ) { // Reward rate of 0.1% per epoch. stake::initialize_for_test_custom( supra_framework, @@ -999,21 +1165,30 @@ module supra_framework::staking_contract { staker: &signer, operator: &signer, amount: u64, - commission: u64, + commission: u64 ) acquires Store { setup(supra_framework, staker, operator, amount); let operator_address = signer::address_of(operator); // Voter is initially set to operator but then updated to be staker. - create_staking_contract(staker, operator_address, operator_address, amount, commission, vector::empty()); - std::features::change_feature_flags_for_testing(supra_framework, vector[MODULE_EVENT, OPERATOR_BENEFICIARY_CHANGE], vector[]); + create_staking_contract( + staker, + operator_address, + operator_address, + amount, + commission, + vector::empty() + ); + std::features::change_feature_flags_for_testing( + supra_framework, + vector[MODULE_EVENT, OPERATOR_BENEFICIARY_CHANGE], + vector[] + ); } #[test(supra_framework = @0x1, staker = @0x123, operator = @0x234)] public entry fun test_end_to_end( - supra_framework: &signer, - staker: &signer, - operator: &signer + supra_framework: &signer, staker: &signer, operator: &signer ) acquires Store, BeneficiaryForOperator { setup_staking_contract(supra_framework, staker, operator, INITIAL_BALANCE, 10); let staker_address = signer::address_of(staker); @@ -1024,7 +1199,10 @@ module supra_framework::staking_contract { // Verify that the stake pool has been set up properly. let pool_address = stake_pool_address(staker_address, operator_address); stake::assert_stake_pool(pool_address, INITIAL_BALANCE, 0, 0, 0); - assert!(last_recorded_principal(staker_address, operator_address) == INITIAL_BALANCE, 0); + assert!( + last_recorded_principal(staker_address, operator_address) == INITIAL_BALANCE, + 0 + ); // Operator joins the validator set. let (_sk, pk) = stake::generate_identity(); @@ -1037,12 +1215,20 @@ module supra_framework::staking_contract { stake::assert_stake_pool(pool_address, new_balance, 0, 0, 0); // Operator claims 10% of rewards so far as commissions. - let expected_commission_1 = (new_balance - last_recorded_principal(staker_address, operator_address)) / 10; + let expected_commission_1 = + (new_balance - last_recorded_principal(staker_address, operator_address)) / 10; new_balance = new_balance - expected_commission_1; request_commission(operator, staker_address, operator_address); stake::assert_stake_pool(pool_address, new_balance, 0, 0, expected_commission_1); - assert!(last_recorded_principal(staker_address, operator_address) == new_balance, 0); - assert_distribution(staker_address, operator_address, operator_address, expected_commission_1); + assert!( + last_recorded_principal(staker_address, operator_address) == new_balance, 0 + ); + assert_distribution( + staker_address, + operator_address, + operator_address, + expected_commission_1 + ); stake::fast_forward_to_unlock(pool_address); // Both original stake and operator commissions have received rewards. @@ -1061,18 +1247,30 @@ module supra_framework::staking_contract { let previous_principal = last_recorded_principal(staker_address, operator_address); add_stake(staker, operator_address, INITIAL_BALANCE); stake::assert_stake_pool(pool_address, new_balance, 0, INITIAL_BALANCE, 0); - assert!(last_recorded_principal(staker_address, operator_address) == previous_principal + INITIAL_BALANCE, 0); + assert!( + last_recorded_principal(staker_address, operator_address) + == previous_principal + INITIAL_BALANCE, + 0 + ); // The newly added stake didn't receive any rewards because it was only added in the new epoch. stake::end_epoch(); new_balance = with_rewards(new_balance) + INITIAL_BALANCE; // Second round of commission request/withdrawal. - let expected_commission_2 = (new_balance - last_recorded_principal(staker_address, operator_address)) / 10; + let expected_commission_2 = + (new_balance - last_recorded_principal(staker_address, operator_address)) / 10; new_balance = new_balance - expected_commission_2; request_commission(operator, staker_address, operator_address); - assert_distribution(staker_address, operator_address, operator_address, expected_commission_2); - assert!(last_recorded_principal(staker_address, operator_address) == new_balance, 0); + assert_distribution( + staker_address, + operator_address, + operator_address, + expected_commission_2 + ); + assert!( + last_recorded_principal(staker_address, operator_address) == new_balance, 0 + ); stake::fast_forward_to_unlock(pool_address); expected_commission_2 = with_rewards(expected_commission_2); distribute(staker_address, operator_address); @@ -1087,20 +1285,31 @@ module supra_framework::staking_contract { new_balance = with_rewards(new_balance); // Staker withdraws all stake, which should also request commission distribution. - let unpaid_commission = (new_balance - last_recorded_principal(staker_address, operator_address)) / 10; + let unpaid_commission = + (new_balance - last_recorded_principal(staker_address, operator_address)) / 10; unlock_stake(staker, operator_address, new_balance); stake::assert_stake_pool(pool_address, 0, 0, 0, new_balance); - assert_distribution(staker_address, operator_address, operator_address, unpaid_commission); + assert_distribution( + staker_address, + operator_address, + operator_address, + unpaid_commission + ); let withdrawn_amount = new_balance - unpaid_commission; - assert_distribution(staker_address, operator_address, staker_address, withdrawn_amount); + assert_distribution( + staker_address, operator_address, staker_address, withdrawn_amount + ); assert!(last_recorded_principal(staker_address, operator_address) == 0, 0); // End epoch. The stake pool should get kicked out of the validator set as it has 0 remaining active stake. stake::fast_forward_to_unlock(pool_address); // Operator should still earn 10% commission on the rewards on top of the staker's withdrawn_amount. - let commission_on_withdrawn_amount = (with_rewards(withdrawn_amount) - withdrawn_amount) / 10; - unpaid_commission = with_rewards(unpaid_commission) + commission_on_withdrawn_amount; - withdrawn_amount = with_rewards(withdrawn_amount) - commission_on_withdrawn_amount; + let commission_on_withdrawn_amount = + (with_rewards(withdrawn_amount) - withdrawn_amount) / 10; + unpaid_commission = with_rewards(unpaid_commission) + + commission_on_withdrawn_amount; + withdrawn_amount = with_rewards(withdrawn_amount) + - commission_on_withdrawn_amount; stake::assert_stake_pool(pool_address, 0, with_rewards(new_balance), 0, 0); assert!(stake::get_validator_state(pool_address) == VALIDATOR_STATUS_INACTIVE, 0); @@ -1108,7 +1317,10 @@ module supra_framework::staking_contract { distribute(staker_address, operator_address); assert_no_pending_distributions(staker_address, operator_address); operator_balance = coin::balance(operator_address); - assert!(operator_balance == expected_operator_balance + unpaid_commission, operator_balance); + assert!( + operator_balance == expected_operator_balance + unpaid_commission, + operator_balance + ); let staker_balance = coin::balance(staker_address); // Staker receives the extra dust due to rounding error. assert!(staker_balance == withdrawn_amount + 1, staker_balance); @@ -1117,7 +1329,8 @@ module supra_framework::staking_contract { #[test(supra_framework = @0x1, staker = @0x123, operator = @0x234)] public entry fun test_operator_cannot_request_same_commission_multiple_times( - supra_framework: &signer, staker: &signer, operator: &signer) acquires Store, BeneficiaryForOperator { + supra_framework: &signer, staker: &signer, operator: &signer + ) acquires Store, BeneficiaryForOperator { setup_staking_contract(supra_framework, staker, operator, INITIAL_BALANCE, 10); let staker_address = signer::address_of(staker); let operator_address = signer::address_of(operator); @@ -1134,18 +1347,35 @@ module supra_framework::staking_contract { stake::assert_stake_pool(pool_address, new_balance, 0, 0, 0); // Operator tries to request commission multiple times. But their distribution shouldn't change. - let expected_commission = (new_balance - last_recorded_principal(staker_address, operator_address)) / 10; + let expected_commission = + (new_balance - last_recorded_principal(staker_address, operator_address)) / 10; request_commission(operator, staker_address, operator_address); - assert_distribution(staker_address, operator_address, operator_address, expected_commission); + assert_distribution( + staker_address, + operator_address, + operator_address, + expected_commission + ); request_commission(operator, staker_address, operator_address); - assert_distribution(staker_address, operator_address, operator_address, expected_commission); + assert_distribution( + staker_address, + operator_address, + operator_address, + expected_commission + ); request_commission(operator, staker_address, operator_address); - assert_distribution(staker_address, operator_address, operator_address, expected_commission); + assert_distribution( + staker_address, + operator_address, + operator_address, + expected_commission + ); } #[test(supra_framework = @0x1, staker = @0x123, operator = @0x234)] public entry fun test_unlock_rewards( - supra_framework: &signer, staker: &signer, operator: &signer) acquires Store, BeneficiaryForOperator { + supra_framework: &signer, staker: &signer, operator: &signer + ) acquires Store, BeneficiaryForOperator { setup_staking_contract(supra_framework, staker, operator, INITIAL_BALANCE, 10); let staker_address = signer::address_of(staker); let operator_address = signer::address_of(operator); @@ -1166,8 +1396,15 @@ module supra_framework::staking_contract { let accumulated_rewards = new_balance - INITIAL_BALANCE; let expected_commission = accumulated_rewards / 10; let staker_rewards = accumulated_rewards - expected_commission; - assert_distribution(staker_address, operator_address, staker_address, staker_rewards); - assert_distribution(staker_address, operator_address, operator_address, expected_commission); + assert_distribution( + staker_address, operator_address, staker_address, staker_rewards + ); + assert_distribution( + staker_address, + operator_address, + operator_address, + expected_commission + ); } #[test(supra_framework = @0x1, staker = @0x123, operator = @0x234)] @@ -1175,12 +1412,19 @@ module supra_framework::staking_contract { public entry fun test_staker_cannot_create_same_staking_contract_multiple_times( supra_framework: &signer, staker: &signer, - operator: &signer, + operator: &signer ) acquires Store { setup_staking_contract(supra_framework, staker, operator, INITIAL_BALANCE, 10); let operator_address = signer::address_of(operator); stake::mint(staker, INITIAL_BALANCE); - create_staking_contract(staker, operator_address, operator_address, INITIAL_BALANCE, 10, vector::empty()); + create_staking_contract( + staker, + operator_address, + operator_address, + INITIAL_BALANCE, + 10, + vector::empty() + ); } #[test(supra_framework = @0x1, staker = @0x123, operator = @0x234)] @@ -1188,7 +1432,7 @@ module supra_framework::staking_contract { public entry fun test_staker_cannot_create_staking_contract_with_invalid_commission( supra_framework: &signer, staker: &signer, - operator: &signer, + operator: &signer ) acquires Store { setup_staking_contract(supra_framework, staker, operator, INITIAL_BALANCE, 101); } @@ -1198,7 +1442,7 @@ module supra_framework::staking_contract { public entry fun test_staker_cannot_create_staking_contract_with_less_than_min_stake_required( supra_framework: &signer, staker: &signer, - operator: &signer, + operator: &signer ) acquires Store { setup_staking_contract(supra_framework, staker, operator, 50, 100); } @@ -1207,7 +1451,7 @@ module supra_framework::staking_contract { public entry fun test_update_voter( supra_framework: &signer, staker: &signer, - operator: &signer, + operator: &signer ) acquires Store { setup_staking_contract(supra_framework, staker, operator, INITIAL_BALANCE, 10); let staker_address = signer::address_of(staker); @@ -1224,7 +1468,7 @@ module supra_framework::staking_contract { public entry fun test_reset_lockup( supra_framework: &signer, staker: &signer, - operator: &signer, + operator: &signer ) acquires Store { setup_staking_contract(supra_framework, staker, operator, INITIAL_BALANCE, 10); let staker_address = signer::address_of(staker); @@ -1236,12 +1480,14 @@ module supra_framework::staking_contract { assert!(origin_lockup_expiration < stake::get_lockup_secs(pool_address), 0); } - #[test(supra_framework = @0x1, staker = @0x123, operator_1 = @0x234, operator_2 = @0x345)] + #[test( + supra_framework = @0x1, staker = @0x123, operator_1 = @0x234, operator_2 = @0x345 + )] public entry fun test_staker_can_switch_operator( supra_framework: &signer, staker: &signer, operator_1: &signer, - operator_2: &signer, + operator_2: &signer ) acquires Store, BeneficiaryForOperator { setup_staking_contract(supra_framework, staker, operator_1, INITIAL_BALANCE, 10); account::create_account_for_test(signer::address_of(operator_2)); @@ -1263,11 +1509,20 @@ module supra_framework::staking_contract { // commission to operator 1. let new_balance = with_rewards(INITIAL_BALANCE); let commission_for_operator_1 = (new_balance - INITIAL_BALANCE) / 10; - assert_distribution(staker_address, operator_2_address, operator_1_address, commission_for_operator_1); + assert_distribution( + staker_address, + operator_2_address, + operator_1_address, + commission_for_operator_1 + ); // Unpaid commission should be unlocked from the stake pool. new_balance = new_balance - commission_for_operator_1; - stake::assert_stake_pool(pool_address, new_balance, 0, 0, commission_for_operator_1); - assert!(last_recorded_principal(staker_address, operator_2_address) == new_balance, 0); + stake::assert_stake_pool( + pool_address, new_balance, 0, 0, commission_for_operator_1 + ); + assert!( + last_recorded_principal(staker_address, operator_2_address) == new_balance, 0 + ); // The stake pool's validator should not have left the validator set. assert!(stake_pool_address(staker_address, operator_2_address) == pool_address, 1); @@ -1280,19 +1535,33 @@ module supra_framework::staking_contract { // operator_2; let commission_on_operator_1_distribution = (with_rewards(commission_for_operator_1) - commission_for_operator_1) / 5; - commission_for_operator_1 = with_rewards(commission_for_operator_1) - commission_on_operator_1_distribution; + commission_for_operator_1 = with_rewards(commission_for_operator_1) + - commission_on_operator_1_distribution; // Verify that when commissions are withdrawn, previous pending distribution to operator 1 also happens. // Then new commission of 20% is paid to operator 2. let commission_for_operator_2 = - (new_balance - last_recorded_principal(staker_address, operator_2_address)) / 5; + (new_balance - last_recorded_principal(staker_address, operator_2_address)) + / 5; new_balance = new_balance - commission_for_operator_2; request_commission(operator_2, staker_address, operator_2_address); - assert_distribution(staker_address, operator_2_address, operator_2_address, commission_for_operator_2); + assert_distribution( + staker_address, + operator_2_address, + operator_2_address, + commission_for_operator_2 + ); let operator_1_balance = coin::balance(operator_1_address); - assert!(operator_1_balance == INITIAL_BALANCE + commission_for_operator_1, operator_1_balance); - stake::assert_stake_pool(pool_address, new_balance, 0, 0, commission_for_operator_2); - assert!(last_recorded_principal(staker_address, operator_2_address) == new_balance, 0); + assert!( + operator_1_balance == INITIAL_BALANCE + commission_for_operator_1, + operator_1_balance + ); + stake::assert_stake_pool( + pool_address, new_balance, 0, 0, commission_for_operator_2 + ); + assert!( + last_recorded_principal(staker_address, operator_2_address) == new_balance, 0 + ); stake::fast_forward_to_unlock(pool_address); // Operator 2's commission is distributed. @@ -1301,24 +1570,28 @@ module supra_framework::staking_contract { new_balance = with_rewards(new_balance); commission_for_operator_2 = with_rewards(commission_for_operator_2); assert!( - operator_2_balance == INITIAL_BALANCE + commission_for_operator_2 + commission_on_operator_1_distribution, - operator_2_balance, + operator_2_balance + == INITIAL_BALANCE + commission_for_operator_2 + + commission_on_operator_1_distribution, + operator_2_balance ); stake::assert_stake_pool( pool_address, new_balance, 0, 0, - 0, + 0 ); } - #[test(supra_framework = @0x1, staker = @0x123, operator_1 = @0x234, operator_2 = @0x345)] + #[test( + supra_framework = @0x1, staker = @0x123, operator_1 = @0x234, operator_2 = @0x345 + )] public entry fun test_staker_can_switch_operator_with_same_commission( supra_framework: &signer, staker: &signer, operator_1: &signer, - operator_2: &signer, + operator_2: &signer ) acquires Store, BeneficiaryForOperator { setup_staking_contract(supra_framework, staker, operator_1, INITIAL_BALANCE, 10); let staker_address = signer::address_of(staker); @@ -1326,20 +1599,30 @@ module supra_framework::staking_contract { let operator_2_address = signer::address_of(operator_2); // Switch operators. - switch_operator_with_same_commission(staker, operator_1_address, operator_2_address); + switch_operator_with_same_commission( + staker, operator_1_address, operator_2_address + ); // The staking_contract should now be associated with operator 2 but with same commission rate. assert!(staking_contract_exists(staker_address, operator_2_address), 0); assert!(!staking_contract_exists(staker_address, operator_1_address), 1); assert!(commission_percentage(staker_address, operator_2_address) == 10, 2); } - #[test(supra_framework = @0x1, staker = @0x123, operator1 = @0x234, beneficiary = @0x345, operator2 = @0x456)] + #[ + test( + supra_framework = @0x1, + staker = @0x123, + operator1 = @0x234, + beneficiary = @0x345, + operator2 = @0x456 + ) + ] public entry fun test_operator_can_set_beneficiary( supra_framework: &signer, staker: &signer, operator1: &signer, beneficiary: &signer, - operator2: &signer, + operator2: &signer ) acquires Store, BeneficiaryForOperator { setup_staking_contract(supra_framework, staker, operator1, INITIAL_BALANCE, 10); let staker_address = signer::address_of(staker); @@ -1355,7 +1638,11 @@ module supra_framework::staking_contract { // Verify that the stake pool has been set up properly. let pool_address = stake_pool_address(staker_address, operator1_address); stake::assert_stake_pool(pool_address, INITIAL_BALANCE, 0, 0, 0); - assert!(last_recorded_principal(staker_address, operator1_address) == INITIAL_BALANCE, 0); + assert!( + last_recorded_principal(staker_address, operator1_address) + == INITIAL_BALANCE, + 0 + ); assert!(stake::get_operator(pool_address) == operator1_address, 0); assert!(beneficiary_for_operator(operator1_address) == operator1_address, 0); @@ -1374,12 +1661,21 @@ module supra_framework::staking_contract { stake::assert_stake_pool(pool_address, new_balance, 0, 0, 0); // Operator claims 10% of rewards so far as commissions. - let expected_commission_1 = (new_balance - last_recorded_principal(staker_address, operator1_address)) / 10; + let expected_commission_1 = + (new_balance - last_recorded_principal(staker_address, operator1_address)) + / 10; new_balance = new_balance - expected_commission_1; request_commission(operator1, staker_address, operator1_address); stake::assert_stake_pool(pool_address, new_balance, 0, 0, expected_commission_1); - assert!(last_recorded_principal(staker_address, operator1_address) == new_balance, 0); - assert_distribution(staker_address, operator1_address, operator1_address, expected_commission_1); + assert!( + last_recorded_principal(staker_address, operator1_address) == new_balance, 0 + ); + assert_distribution( + staker_address, + operator1_address, + operator1_address, + expected_commission_1 + ); stake::fast_forward_to_unlock(pool_address); // Both original stake and operator commissions have received rewards. @@ -1401,7 +1697,8 @@ module supra_framework::staking_contract { switch_operator(staker, operator1_address, operator2_address, 10); stake::end_epoch(); - let (_, accumulated_rewards, _) = staking_contract_amounts(staker_address, operator2_address); + let (_, accumulated_rewards, _) = + staking_contract_amounts(staker_address, operator2_address); let expected_commission = accumulated_rewards / 10; @@ -1416,12 +1713,15 @@ module supra_framework::staking_contract { // Assert that the rewards go to operator2, and the balance of the operator1's beneficiay remains the same. assert!(coin::balance(operator2_address) >= expected_commission, 1); - assert!(coin::balance(beneficiary_address) == old_beneficiay_balance, 1); + assert!( + coin::balance(beneficiary_address) == old_beneficiay_balance, 1 + ); } #[test(supra_framework = @0x1, staker = @0x123, operator = @0x234)] public entry fun test_staker_can_withdraw_partial_stake( - supra_framework: &signer, staker: &signer, operator: &signer) acquires Store, BeneficiaryForOperator { + supra_framework: &signer, staker: &signer, operator: &signer + ) acquires Store, BeneficiaryForOperator { let initial_balance = INITIAL_BALANCE * 2; setup_staking_contract(supra_framework, staker, operator, initial_balance, 10); let staker_address = signer::address_of(staker); @@ -1430,7 +1730,7 @@ module supra_framework::staking_contract { // Operator joins the validator set so rewards are generated. let (_sk, pk) = stake::generate_identity(); - stake::join_validator_set_for_test(&pk, operator, pool_address, true); + stake::join_validator_set_for_test(&pk, operator, pool_address, true); assert!(stake::get_validator_state(pool_address) == VALIDATOR_STATUS_ACTIVE, 1); // Fast forward to generate rewards. @@ -1443,10 +1743,25 @@ module supra_framework::staking_contract { let unpaid_commission = (new_balance - initial_balance) / 10; let new_balance = new_balance - withdrawn_stake - unpaid_commission; unlock_stake(staker, operator_address, withdrawn_stake); - stake::assert_stake_pool(pool_address, new_balance, 0, 0, withdrawn_stake + unpaid_commission); - assert_distribution(staker_address, operator_address, operator_address, unpaid_commission); - assert_distribution(staker_address, operator_address, staker_address, withdrawn_stake); - assert!(last_recorded_principal(staker_address, operator_address) == new_balance, 0); + stake::assert_stake_pool( + pool_address, + new_balance, + 0, + 0, + withdrawn_stake + unpaid_commission + ); + assert_distribution( + staker_address, + operator_address, + operator_address, + unpaid_commission + ); + assert_distribution( + staker_address, operator_address, staker_address, withdrawn_stake + ); + assert!( + last_recorded_principal(staker_address, operator_address) == new_balance, 0 + ); // The validator is still in the active set as its remaining stake is still above min required. stake::fast_forward_to_unlock(pool_address); @@ -1454,10 +1769,17 @@ module supra_framework::staking_contract { unpaid_commission = with_rewards(unpaid_commission); // Commission should still be charged on the rewards on top of withdrawn_stake. // So the operator should receive 10% of the rewards on top of withdrawn_stake. - let commission_on_withdrawn_stake = (with_rewards(withdrawn_stake) - withdrawn_stake) / 10; + let commission_on_withdrawn_stake = + (with_rewards(withdrawn_stake) - withdrawn_stake) / 10; unpaid_commission = unpaid_commission + commission_on_withdrawn_stake; withdrawn_stake = with_rewards(withdrawn_stake) - commission_on_withdrawn_stake; - stake::assert_stake_pool(pool_address, new_balance, withdrawn_stake + unpaid_commission, 0, 0); + stake::assert_stake_pool( + pool_address, + new_balance, + withdrawn_stake + unpaid_commission, + 0, + 0 + ); assert!(stake::get_validator_state(pool_address) == VALIDATOR_STATUS_ACTIVE, 0); // Distribute and verify balances. @@ -1471,7 +1793,8 @@ module supra_framework::staking_contract { #[test(supra_framework = @0x1, staker = @0x123, operator = @0x234)] public entry fun test_staker_can_withdraw_partial_stake_if_operator_never_joined_validator_set( - supra_framework: &signer, staker: &signer, operator: &signer) acquires Store, BeneficiaryForOperator { + supra_framework: &signer, staker: &signer, operator: &signer + ) acquires Store, BeneficiaryForOperator { let initial_balance = INITIAL_BALANCE * 2; setup_staking_contract(supra_framework, staker, operator, initial_balance, 10); let staker_address = signer::address_of(staker); @@ -1488,8 +1811,12 @@ module supra_framework::staking_contract { unlock_stake(staker, operator_address, withdrawn_stake); stake::assert_stake_pool(pool_address, new_balance, 0, 0, withdrawn_stake); assert_distribution(staker_address, operator_address, operator_address, 0); - assert_distribution(staker_address, operator_address, staker_address, withdrawn_stake); - assert!(last_recorded_principal(staker_address, operator_address) == new_balance, 0); + assert_distribution( + staker_address, operator_address, staker_address, withdrawn_stake + ); + assert!( + last_recorded_principal(staker_address, operator_address) == new_balance, 0 + ); // Distribute and verify balances. distribute(staker_address, operator_address); @@ -1504,7 +1831,8 @@ module supra_framework::staking_contract { #[test(supra_framework = @0x1, staker = @0x123, operator = @0x234)] public entry fun test_multiple_distributions_added_before_distribute( - supra_framework: &signer, staker: &signer, operator: &signer) acquires Store, BeneficiaryForOperator { + supra_framework: &signer, staker: &signer, operator: &signer + ) acquires Store, BeneficiaryForOperator { let initial_balance = INITIAL_BALANCE * 2; setup_staking_contract(supra_framework, staker, operator, initial_balance, 10); let staker_address = signer::address_of(staker); @@ -1513,7 +1841,7 @@ module supra_framework::staking_contract { // Operator joins the validator set so rewards are generated. let (_sk, pk) = stake::generate_identity(); - stake::join_validator_set_for_test(&pk, operator, pool_address, true); + stake::join_validator_set_for_test(&pk, operator, pool_address, true); assert!(stake::get_validator_state(pool_address) == VALIDATOR_STATUS_ACTIVE, 1); // Fast forward to generate rewards. @@ -1526,34 +1854,65 @@ module supra_framework::staking_contract { let unpaid_commission = (new_balance - initial_balance) / 10; let new_balance = new_balance - withdrawn_stake - unpaid_commission; unlock_stake(staker, operator_address, withdrawn_stake); - stake::assert_stake_pool(pool_address, new_balance, 0, 0, withdrawn_stake + unpaid_commission); - assert_distribution(staker_address, operator_address, operator_address, unpaid_commission); - assert_distribution(staker_address, operator_address, staker_address, withdrawn_stake); - assert!(last_recorded_principal(staker_address, operator_address) == new_balance, 0); + stake::assert_stake_pool( + pool_address, + new_balance, + 0, + 0, + withdrawn_stake + unpaid_commission + ); + assert_distribution( + staker_address, + operator_address, + operator_address, + unpaid_commission + ); + assert_distribution( + staker_address, operator_address, staker_address, withdrawn_stake + ); + assert!( + last_recorded_principal(staker_address, operator_address) == new_balance, 0 + ); // End epoch to generate some rewards. Staker withdraws another 1/4 of the stake. // Commission should be charged on the rewards earned on the previous 1/4 stake withdrawal. stake::end_epoch(); - let commission_on_withdrawn_stake = (with_rewards(withdrawn_stake) - withdrawn_stake) / 10; + let commission_on_withdrawn_stake = + (with_rewards(withdrawn_stake) - withdrawn_stake) / 10; let commission_on_new_balance = (with_rewards(new_balance) - new_balance) / 10; - unpaid_commission = with_rewards(unpaid_commission) + commission_on_withdrawn_stake + commission_on_new_balance; + unpaid_commission = with_rewards(unpaid_commission) + + commission_on_withdrawn_stake + commission_on_new_balance; new_balance = with_rewards(new_balance) - commission_on_new_balance; let new_withdrawn_stake = new_balance / 4; unlock_stake(staker, operator_address, new_withdrawn_stake); new_balance = new_balance - new_withdrawn_stake; - withdrawn_stake = with_rewards(withdrawn_stake) - commission_on_withdrawn_stake + new_withdrawn_stake; - stake::assert_stake_pool(pool_address, new_balance, 0, 0, withdrawn_stake + unpaid_commission); + withdrawn_stake = with_rewards(withdrawn_stake) - commission_on_withdrawn_stake + + new_withdrawn_stake; + stake::assert_stake_pool( + pool_address, + new_balance, + 0, + 0, + withdrawn_stake + unpaid_commission + ); // There's some small rounding error here. - assert_distribution(staker_address, operator_address, operator_address, unpaid_commission - 1); - assert_distribution(staker_address, operator_address, staker_address, withdrawn_stake); - assert!(last_recorded_principal(staker_address, operator_address) == new_balance, 0); + assert_distribution( + staker_address, + operator_address, + operator_address, + unpaid_commission - 1 + ); + assert_distribution( + staker_address, operator_address, staker_address, withdrawn_stake + ); + assert!( + last_recorded_principal(staker_address, operator_address) == new_balance, 0 + ); } #[test(supra_framework = @0x1, staker = @0x123, operator = @0x234)] public entry fun test_update_commission( - supra_framework: &signer, - staker: &signer, - operator: &signer + supra_framework: &signer, staker: &signer, operator: &signer ) acquires Store, BeneficiaryForOperator, StakingGroupUpdateCommissionEvent { let initial_balance = INITIAL_BALANCE * 2; setup_staking_contract(supra_framework, staker, operator, initial_balance, 10); @@ -1575,22 +1934,42 @@ module supra_framework::staking_contract { update_commision(staker, operator_address, 5); stake::end_epoch(); let balance_2epoch = with_rewards(balance_1epoch - unpaid_commission); - stake::assert_stake_pool(pool_address, balance_2epoch, 0, 0, with_rewards(unpaid_commission)); + stake::assert_stake_pool( + pool_address, + balance_2epoch, + 0, + 0, + with_rewards(unpaid_commission) + ); } - #[test( - staker = @0xe256f4f4e2986cada739e339895cf5585082ff247464cab8ec56eea726bd2263, - operator = @0x9f0a211d218b082987408f1e393afe1ba0c202c6d280f081399788d3360c7f09 - )] - public entry fun test_get_expected_stake_pool_address(staker: address, operator: address) { - let pool_address = get_expected_stake_pool_address(staker, operator, vector[0x42, 0x42]); - assert!(pool_address == @0xb500b8db823e529929e1f9ec79abd731dcc235a2027b28bbb78d65ee928d001a, 0); + #[ + test( + staker = @0xe256f4f4e2986cada739e339895cf5585082ff247464cab8ec56eea726bd2263, + operator = @0x9f0a211d218b082987408f1e393afe1ba0c202c6d280f081399788d3360c7f09 + ) + ] + public entry fun test_get_expected_stake_pool_address( + staker: address, operator: address + ) { + let pool_address = + get_expected_stake_pool_address(staker, operator, vector[0x42, 0x42]); + assert!( + pool_address + == @0xb500b8db823e529929e1f9ec79abd731dcc235a2027b28bbb78d65ee928d001a, + 0 + ); } #[test_only] public fun assert_staking_contract( - staker: address, operator: address, principal: u64, commission_percentage: u64) acquires Store { - let staking_contract = simple_map::borrow(&borrow_global(staker).staking_contracts, &operator); + staker: address, + operator: address, + principal: u64, + commission_percentage: u64 + ) acquires Store { + let staking_contract = + simple_map::borrow(&borrow_global(staker).staking_contracts, &operator); assert!(staking_contract.principal == principal, staking_contract.principal); assert!( staking_contract.commission_percentage == commission_percentage, @@ -1599,8 +1978,11 @@ module supra_framework::staking_contract { } #[test_only] - public fun assert_no_pending_distributions(staker: address, operator: address) acquires Store { - let staking_contract = simple_map::borrow(&borrow_global(staker).staking_contracts, &operator); + public fun assert_no_pending_distributions( + staker: address, operator: address + ) acquires Store { + let staking_contract = + simple_map::borrow(&borrow_global(staker).staking_contracts, &operator); let distribution_pool = &staking_contract.distribution_pool; let shareholders_count = pool_u64::shareholders_count(distribution_pool); assert!(shareholders_count == 0, shareholders_count); @@ -1610,9 +1992,15 @@ module supra_framework::staking_contract { #[test_only] public fun assert_distribution( - staker: address, operator: address, recipient: address, coins_amount: u64) acquires Store { - let staking_contract = simple_map::borrow(&borrow_global(staker).staking_contracts, &operator); - let distribution_balance = pool_u64::balance(&staking_contract.distribution_pool, recipient); + staker: address, + operator: address, + recipient: address, + coins_amount: u64 + ) acquires Store { + let staking_contract = + simple_map::borrow(&borrow_global(staker).staking_contracts, &operator); + let distribution_balance = + pool_u64::balance(&staking_contract.distribution_pool, recipient); assert!(distribution_balance == coins_amount, distribution_balance); } } diff --git a/aptos-move/framework/supra-framework/sources/staking_contract.spec.move b/aptos-move/framework/supra-framework/sources/staking_contract.spec.move index 4cac10820d783..732254b073d67 100644 --- a/aptos-move/framework/supra-framework/sources/staking_contract.spec.move +++ b/aptos-move/framework/supra-framework/sources/staking_contract.spec.move @@ -75,7 +75,8 @@ spec supra_framework::staking_contract { spec stake_pool_address(staker: address, operator: address): address { include ContractExistsAbortsIf; let staking_contracts = global(staker).staking_contracts; - ensures result == simple_map::spec_get(staking_contracts, operator).pool_address; + ensures result + == simple_map::spec_get(staking_contracts, operator).pool_address; } @@ -90,14 +91,16 @@ spec supra_framework::staking_contract { spec commission_percentage(staker: address, operator: address): u64 { include ContractExistsAbortsIf; let staking_contracts = global(staker).staking_contracts; - ensures result == simple_map::spec_get(staking_contracts, operator).commission_percentage; + ensures result + == simple_map::spec_get(staking_contracts, operator).commission_percentage; } /// Staking_contract exists the stacker/operator pair. spec staking_contract_amounts(staker: address, operator: address): (u64, u64, u64) { // TODO: set because of timeout (property proved). pragma verify_duration_estimate = 120; - requires staking_contract.commission_percentage >= 0 && staking_contract.commission_percentage <= 100; + requires staking_contract.commission_percentage >= 0 + && staking_contract.commission_percentage <= 100; let staking_contracts = global(staker).staking_contracts; let staking_contract = simple_map::spec_get(staking_contracts, operator); @@ -133,9 +136,8 @@ spec supra_framework::staking_contract { } spec fun spec_staking_contract_exists(staker: address, operator: address): bool { - if (!exists(staker)) { - false - } else { + if (!exists(staker)) { false } + else { let store = global(staker); simple_map::spec_contains_key(store.staking_contracts, operator) } @@ -143,12 +145,12 @@ spec supra_framework::staking_contract { /// Account is not frozen and sufficient to withdraw. spec create_staking_contract( - staker: &signer, - operator: address, - voter: address, - amount: u64, - commission_percentage: u64, - contract_creation_seed: vector, + staker: &signer, + operator: address, + voter: address, + amount: u64, + commission_percentage: u64, + contract_creation_seed: vector ) { pragma aborts_if_is_partial; pragma verify_duration_estimate = 120; @@ -161,12 +163,12 @@ spec supra_framework::staking_contract { /// Initialize Store resource if this is the first time the staker has delegated to anyone. /// Cannot create the staking contract if it already exists. spec create_staking_contract_with_coins( - staker: &signer, - operator: address, - voter: address, - coins: Coin, - commission_percentage: u64, - contract_creation_seed: vector, + staker: &signer, + operator: address, + voter: address, + coins: Coin, + commission_percentage: u64, + contract_creation_seed: vector ): address { pragma verify_duration_estimate = 120; pragma aborts_if_is_partial; @@ -208,7 +210,9 @@ spec supra_framework::staking_contract { include stake::AddStakeWithCapAbortsIfAndEnsures { owner_cap }; let post post_store = global(staker_address); - let post post_staking_contract = simple_map::spec_get(post_store.staking_contracts, operator); + let post post_staking_contract = simple_map::spec_get( + post_store.staking_contracts, operator + ); aborts_if staking_contract.principal + amount > MAX_U64; // property 3: Adding stake to the stake pool increases the principal value of the pool, reflecting the @@ -223,7 +227,9 @@ spec supra_framework::staking_contract { include UpdateVoterSchema { staker: staker_address }; let post store = global(staker_address); - let post staking_contract = simple_map::spec_get(store.staking_contracts, operator); + let post staking_contract = simple_map::spec_get( + store.staking_contracts, operator + ); let post pool_address = staking_contract.owner_cap.pool_address; let post new_delegated_voter = global(pool_address).delegated_voter; // property 4: The staker may update the voter of a staking contract, enabling them @@ -240,7 +246,7 @@ spec supra_framework::staking_contract { include IncreaseLockupWithCapAbortsIf { staker: staker_address }; } - spec update_commision (staker: &signer, operator: address, new_commission_percentage: u64) { + spec update_commision(staker: &signer, operator: address, new_commission_percentage: u64) { // TODO: Call `distribute_internal` and could not verify `update_distribution_pool`. // TODO: A data invariant not hold happened here involve with 'pool_u64' #L16. pragma verify = false; @@ -260,10 +266,10 @@ spec supra_framework::staking_contract { } spec request_commission_internal( - operator: address, - staking_contract: &mut StakingContract, - add_distribution_events: &mut EventHandle, - request_commission_events: &mut EventHandle, + operator: address, + staking_contract: &mut StakingContract, + add_distribution_events: &mut EventHandle, + request_commission_events: &mut EventHandle ): u64 { // TODO: A data invariant not hold happened here involve with 'pool_u64' #L16. pragma verify = false; @@ -276,7 +282,8 @@ spec supra_framework::staking_contract { // TODO: Set because of timeout (estimate unknown). pragma verify = false; /// [high-level-req-4] - requires staking_contract.commission_percentage >= 0 && staking_contract.commission_percentage <= 100; + requires staking_contract.commission_percentage >= 0 + && staking_contract.commission_percentage <= 100; let staker_address = signer::address_of(staker); let staking_contracts = global(staker_address).staking_contracts; let staking_contract = simple_map::spec_get(staking_contracts, operator); @@ -294,9 +301,7 @@ spec supra_framework::staking_contract { /// Staking_contract exists the stacker/operator pair. spec switch_operator_with_same_commission( - staker: &signer, - old_operator: address, - new_operator: address, + staker: &signer, old_operator: address, new_operator: address ) { // TODO: These function passed locally however failed in github CI pragma verify_duration_estimate = 120; @@ -308,10 +313,10 @@ spec supra_framework::staking_contract { /// Staking_contract exists the stacker/operator pair. spec switch_operator( - staker: &signer, - old_operator: address, - new_operator: address, - new_commission_percentage: u64, + staker: &signer, + old_operator: address, + new_operator: address, + new_commission_percentage: u64 ) { // TODO: Call `update_distribution_pool` and could not verify `update_distribution_pool`. // TODO: Set because of timeout (estimate unknown). @@ -346,10 +351,10 @@ spec supra_framework::staking_contract { /// The StakePool exists under the pool_address of StakingContract. /// The value of inactive and pending_inactive in the stake_pool is up to MAX_U64. spec distribute_internal( - staker: address, - operator: address, - staking_contract: &mut StakingContract, - distribute_events: &mut EventHandle, + staker: address, + operator: address, + staking_contract: &mut StakingContract, + distribute_events: &mut EventHandle ) { // TODO: These function passed locally however failed in github CI pragma verify_duration_estimate = 120; @@ -358,7 +363,8 @@ spec supra_framework::staking_contract { let pool_address = staking_contract.pool_address; let stake_pool = borrow_global(pool_address); aborts_if !exists(pool_address); - aborts_if stake_pool.inactive.value + stake_pool.pending_inactive.value > MAX_U64; + aborts_if stake_pool.inactive.value + stake_pool.pending_inactive.value + > MAX_U64; aborts_if !exists(staking_contract.owner_cap.pool_address); } @@ -368,18 +374,20 @@ spec supra_framework::staking_contract { } spec add_distribution( - operator: address, - staking_contract: &mut StakingContract, - recipient: address, - coins_amount: u64, - add_distribution_events: &mut EventHandle, + operator: address, + staking_contract: &mut StakingContract, + recipient: address, + coins_amount: u64, + add_distribution_events: &mut EventHandle ) { // TODO: Call `update_distribution_pool` and could not verify `update_distribution_pool`. pragma verify = false; } /// The StakePool exists under the pool_address of StakingContract. - spec get_staking_contract_amounts_internal(staking_contract: &StakingContract): (u64, u64, u64) { + spec get_staking_contract_amounts_internal(staking_contract: &StakingContract): ( + u64, u64, u64 + ) { pragma verify_duration_estimate = 120; include GetStakingContractAmountsAbortsIf; @@ -389,17 +397,18 @@ spec supra_framework::staking_contract { let pending_active = coin::value(stake_pool.pending_active); let total_active_stake = active + pending_active; let accumulated_rewards = total_active_stake - staking_contract.principal; - let commission_amount = accumulated_rewards * staking_contract.commission_percentage / 100; + let commission_amount = accumulated_rewards + * staking_contract.commission_percentage / 100; ensures result_1 == total_active_stake; ensures result_2 == accumulated_rewards; ensures result_3 == commission_amount; } spec create_stake_pool( - staker: &signer, - operator: address, - voter: address, - contract_creation_seed: vector, + staker: &signer, + operator: address, + voter: address, + contract_creation_seed: vector ): (signer, SignerCapability, OwnerCapability) { pragma verify_duration_estimate = 120; include stake::ResourceRequirement; @@ -407,13 +416,17 @@ spec supra_framework::staking_contract { // postconditions account::create_resource_account() let seed_0 = bcs::to_bytes(staker_address); - let seed_1 = concat(concat(concat(seed_0, bcs::to_bytes(operator)), SALT), contract_creation_seed); + let seed_1 = concat( + concat(concat(seed_0, bcs::to_bytes(operator)), SALT), + contract_creation_seed + ); let resource_addr = account::spec_create_resource_address(staker_address, seed_1); include CreateStakePoolAbortsIf { resource_addr }; ensures exists(resource_addr); let post post_account = global(resource_addr); ensures post_account.authentication_key == account::ZERO_AUTH_KEY; - ensures post_account.signer_capability_offer.for == std::option::spec_some(resource_addr); + ensures post_account.signer_capability_offer.for + == std::option::spec_some(resource_addr); // postconditions stake::initialize_stake_owner() ensures exists(resource_addr); @@ -422,18 +435,20 @@ spec supra_framework::staking_contract { let post post_stake_pool = global(post_pool_address); let post post_operator = post_stake_pool.operator_address; let post post_delegated_voter = post_stake_pool.delegated_voter; - ensures resource_addr != operator ==> post_operator == operator; - ensures resource_addr != voter ==> post_delegated_voter == voter; + ensures resource_addr != operator ==> + post_operator == operator; + ensures resource_addr != voter ==> + post_delegated_voter == voter; ensures signer::address_of(result_1) == resource_addr; ensures result_2 == SignerCapability { account: resource_addr }; ensures result_3 == OwnerCapability { pool_address: resource_addr }; } spec update_distribution_pool( - distribution_pool: &mut Pool, - updated_total_coins: u64, - operator: address, - commission_percentage: u64, + distribution_pool: &mut Pool, + updated_total_coins: u64, + operator: address, + commission_percentage: u64 ) { // TODO: complex aborts conditions in the cycle. // pragma verify = false; @@ -505,7 +520,8 @@ spec supra_framework::staking_contract { aborts_if active + pending_active > MAX_U64; // TODO: These function causes the timeout aborts_if total_active_stake < staking_contract.principal; - aborts_if accumulated_rewards * staking_contract.commission_percentage > MAX_U64; + aborts_if accumulated_rewards * staking_contract.commission_percentage + > MAX_U64; } spec schema IncreaseLockupWithCapAbortsIf { @@ -524,17 +540,21 @@ spec supra_framework::staking_contract { let config = global(@supra_framework); let stake_pool = global(pool_address); let old_locked_until_secs = stake_pool.locked_until_secs; - let seconds = global( - @supra_framework - ).microseconds / timestamp::MICRO_CONVERSION_FACTOR; + let seconds = global(@supra_framework).microseconds + / timestamp::MICRO_CONVERSION_FACTOR; let new_locked_until_secs = seconds + config.recurring_lockup_duration_secs; aborts_if seconds + config.recurring_lockup_duration_secs > MAX_U64; - aborts_if old_locked_until_secs > new_locked_until_secs || old_locked_until_secs == new_locked_until_secs; + aborts_if old_locked_until_secs > new_locked_until_secs + || old_locked_until_secs == new_locked_until_secs; aborts_if !exists(@supra_framework); let post post_store = global(staker); - let post post_staking_contract = simple_map::spec_get(post_store.staking_contracts, operator); - let post post_stake_pool = global(post_staking_contract.owner_cap.pool_address); + let post post_staking_contract = simple_map::spec_get( + post_store.staking_contracts, operator + ); + let post post_stake_pool = global( + post_staking_contract.owner_cap.pool_address + ); ensures post_stake_pool.locked_until_secs == new_locked_until_secs; } @@ -554,8 +574,10 @@ spec supra_framework::staking_contract { let staker_address = signer::address_of(staker); let account = global(staker_address); - aborts_if !exists(staker_address) && !exists(staker_address); - aborts_if !exists(staker_address) && account.guid_creation_num + 9 >= account::MAX_GUID_CREATION_NUM; + aborts_if !exists(staker_address) + && !exists(staker_address); + aborts_if !exists(staker_address) + && account.guid_creation_num + 9 >= account::MAX_GUID_CREATION_NUM; /// [high-level-req-1] ensures exists(staker_address); @@ -571,7 +593,6 @@ spec supra_framework::staking_contract { // let resource_addr = account::spec_create_resource_address(staker_address, seed_1); // include CreateStakePoolAbortsIf {resource_addr}; - // Verify stake::add_stake_with_cap() let owner_cap = simple_map::spec_get(store.staking_contracts, operator).owner_cap; // TODO: this property causes timeout @@ -585,11 +606,12 @@ spec supra_framework::staking_contract { spec schema PreconditionsInCreateContract { requires exists(@supra_framework); requires exists(@supra_framework); - requires exists( - @supra_framework - ) || !std::features::spec_periodical_reward_rate_decrease_enabled(); + requires exists(@supra_framework) + || !std::features::spec_periodical_reward_rate_decrease_enabled(); requires exists(@supra_framework); - requires exists(@supra_framework); + requires exists( + @supra_framework + ); requires exists(@supra_framework); } @@ -601,21 +623,24 @@ spec supra_framework::staking_contract { // postconditions account::create_resource_account() let acc = global(resource_addr); - aborts_if exists(resource_addr) && (len( - acc.signer_capability_offer.for.vec - ) != 0 || acc.sequence_number != 0); - aborts_if !exists(resource_addr) && len(bcs::to_bytes(resource_addr)) != 32; + aborts_if exists(resource_addr) + && ( + len(acc.signer_capability_offer.for.vec) != 0 + || acc.sequence_number != 0 + ); + aborts_if !exists(resource_addr) + && len(bcs::to_bytes(resource_addr)) != 32; aborts_if len(account::ZERO_AUTH_KEY) != 32; // postconditions stake::initialize_stake_owner() aborts_if exists(resource_addr); let allowed = global(@supra_framework); - aborts_if exists(@supra_framework) && !contains(allowed.accounts, resource_addr); + aborts_if exists(@supra_framework) + && !contains(allowed.accounts, resource_addr); aborts_if exists(resource_addr); aborts_if exists(resource_addr); // 12 is the times that calls 'events::guids' - aborts_if exists( - resource_addr - ) && acc.guid_creation_num + 12 >= account::MAX_GUID_CREATION_NUM; + aborts_if exists(resource_addr) + && acc.guid_creation_num + 12 >= account::MAX_GUID_CREATION_NUM; } } diff --git a/aptos-move/framework/supra-framework/sources/staking_proxy.move b/aptos-move/framework/supra-framework/sources/staking_proxy.move index 566afc03ad6fe..8670cadb5f358 100644 --- a/aptos-move/framework/supra-framework/sources/staking_proxy.move +++ b/aptos-move/framework/supra-framework/sources/staking_proxy.move @@ -6,64 +6,95 @@ module supra_framework::staking_proxy { use supra_framework::staking_contract; use supra_framework::vesting; - public entry fun set_operator(owner: &signer, old_operator: address, new_operator: address) { + public entry fun set_operator( + owner: &signer, old_operator: address, new_operator: address + ) { set_vesting_contract_operator(owner, old_operator, new_operator); set_staking_contract_operator(owner, old_operator, new_operator); set_stake_pool_operator(owner, new_operator); } - public entry fun set_voter(owner: &signer, operator: address, new_voter: address) { + public entry fun set_voter( + owner: &signer, operator: address, new_voter: address + ) { set_vesting_contract_voter(owner, operator, new_voter); set_staking_contract_voter(owner, operator, new_voter); set_stake_pool_voter(owner, new_voter); } - public entry fun set_vesting_contract_operator(owner: &signer, old_operator: address, new_operator: address) { + public entry fun set_vesting_contract_operator( + owner: &signer, old_operator: address, new_operator: address + ) { let owner_address = signer::address_of(owner); let vesting_contracts = &vesting::vesting_contracts(owner_address); - vector::for_each_ref(vesting_contracts, |vesting_contract| { - let vesting_contract = *vesting_contract; - if (vesting::operator(vesting_contract) == old_operator) { - let current_commission_percentage = vesting::operator_commission_percentage(vesting_contract); - vesting::update_operator(owner, vesting_contract, new_operator, current_commission_percentage); - }; - }); + vector::for_each_ref( + vesting_contracts, + |vesting_contract| { + let vesting_contract = *vesting_contract; + if (vesting::operator(vesting_contract) == old_operator) { + let current_commission_percentage = + vesting::operator_commission_percentage(vesting_contract); + vesting::update_operator( + owner, + vesting_contract, + new_operator, + current_commission_percentage + ); + }; + } + ); } - public entry fun set_staking_contract_operator(owner: &signer, old_operator: address, new_operator: address) { + public entry fun set_staking_contract_operator( + owner: &signer, old_operator: address, new_operator: address + ) { let owner_address = signer::address_of(owner); if (staking_contract::staking_contract_exists(owner_address, old_operator)) { - let current_commission_percentage = staking_contract::commission_percentage(owner_address, old_operator); - staking_contract::switch_operator(owner, old_operator, new_operator, current_commission_percentage); + let current_commission_percentage = + staking_contract::commission_percentage(owner_address, old_operator); + staking_contract::switch_operator( + owner, old_operator, new_operator, current_commission_percentage + ); }; } - public entry fun set_stake_pool_operator(owner: &signer, new_operator: address) { + public entry fun set_stake_pool_operator( + owner: &signer, new_operator: address + ) { let owner_address = signer::address_of(owner); if (stake::stake_pool_exists(owner_address)) { stake::set_operator(owner, new_operator); }; } - public entry fun set_vesting_contract_voter(owner: &signer, operator: address, new_voter: address) { + public entry fun set_vesting_contract_voter( + owner: &signer, operator: address, new_voter: address + ) { let owner_address = signer::address_of(owner); let vesting_contracts = &vesting::vesting_contracts(owner_address); - vector::for_each_ref(vesting_contracts, |vesting_contract| { - let vesting_contract = *vesting_contract; - if (vesting::operator(vesting_contract) == operator) { - vesting::update_voter(owner, vesting_contract, new_voter); - }; - }); + vector::for_each_ref( + vesting_contracts, + |vesting_contract| { + let vesting_contract = *vesting_contract; + if (vesting::operator(vesting_contract) == operator) { + vesting::update_voter(owner, vesting_contract, new_voter); + }; + } + ); } - public entry fun set_staking_contract_voter(owner: &signer, operator: address, new_voter: address) { + public entry fun set_staking_contract_voter( + owner: &signer, operator: address, new_voter: address + ) { let owner_address = signer::address_of(owner); if (staking_contract::staking_contract_exists(owner_address, operator)) { staking_contract::update_voter(owner, operator, new_voter); }; } - public entry fun set_stake_pool_voter(owner: &signer, new_voter: address) { + public entry fun set_stake_pool_voter( + owner: &signer, new_voter: address + ) { if (stake::stake_pool_exists(signer::address_of(owner))) { stake::set_delegated_voter(owner, new_voter); }; @@ -72,36 +103,55 @@ module supra_framework::staking_proxy { #[test_only] const INITIAL_BALANCE: u64 = 100000000000000; // 1M SUPRA coins with 8 decimals. - #[test( - supra_framework = @0x1, - owner = @0x123, - operator_1 = @0x234, - operator_2 = @0x345, - new_operator = @0x567, - )] + #[ + test( + supra_framework = @0x1, + owner = @0x123, + operator_1 = @0x234, + operator_2 = @0x345, + new_operator = @0x567 + ) + ] public entry fun test_set_operator( supra_framework: &signer, owner: &signer, operator_1: &signer, operator_2: &signer, - new_operator: &signer, + new_operator: &signer ) { let owner_address = signer::address_of(owner); let operator_1_address = signer::address_of(operator_1); let operator_2_address = signer::address_of(operator_2); let new_operator_address = signer::address_of(new_operator); vesting::setup( - supra_framework, &vector[owner_address, operator_1_address, operator_2_address, new_operator_address]); - staking_contract::setup_staking_contract(supra_framework, owner, operator_1, INITIAL_BALANCE, 0); - staking_contract::setup_staking_contract(supra_framework, owner, operator_2, INITIAL_BALANCE, 0); + supra_framework, + &vector[ + owner_address, + operator_1_address, + operator_2_address, + new_operator_address + ] + ); + staking_contract::setup_staking_contract( + supra_framework, owner, operator_1, INITIAL_BALANCE, 0 + ); + staking_contract::setup_staking_contract( + supra_framework, owner, operator_2, INITIAL_BALANCE, 0 + ); - let vesting_contract_1 = vesting::setup_vesting_contract(owner, &vector[@11], &vector[INITIAL_BALANCE], owner_address, 0); + let vesting_contract_1 = + vesting::setup_vesting_contract( + owner, &vector[@11], &vector[INITIAL_BALANCE], owner_address, 0 + ); vesting::update_operator(owner, vesting_contract_1, operator_1_address, 0); - let vesting_contract_2 = vesting::setup_vesting_contract(owner, &vector[@12], &vector[INITIAL_BALANCE], owner_address, 0); + let vesting_contract_2 = + vesting::setup_vesting_contract( + owner, &vector[@12], &vector[INITIAL_BALANCE], owner_address, 0 + ); vesting::update_operator(owner, vesting_contract_2, operator_2_address, 0); let (_sk, pk) = stake::generate_identity(); - stake::initialize_test_validator(&pk, owner, INITIAL_BALANCE, false, false); + stake::initialize_test_validator(&pk, owner, INITIAL_BALANCE, false, false); stake::set_operator(owner, operator_1_address); set_operator(owner, operator_1_address, new_operator_address); @@ -109,84 +159,136 @@ module supra_framework::staking_proxy { assert!(stake::get_operator(owner_address) == new_operator_address, 0); // Staking contract has been switched from operator 1 to new operator. // Staking contract with operator_2 should stay unchanged. - assert!(staking_contract::staking_contract_exists(owner_address, new_operator_address), 1); - assert!(!staking_contract::staking_contract_exists(owner_address, operator_1_address), 2); - assert!(staking_contract::staking_contract_exists(owner_address, operator_2_address), 3); + assert!( + staking_contract::staking_contract_exists(owner_address, new_operator_address), + 1 + ); + assert!( + !staking_contract::staking_contract_exists(owner_address, operator_1_address), + 2 + ); + assert!( + staking_contract::staking_contract_exists(owner_address, operator_2_address), + 3 + ); // Vesting contract 1 has been switched from operator 1 to new operator while vesting contract 2 stays unchanged assert!(vesting::operator(vesting_contract_1) == new_operator_address, 4); assert!(vesting::operator(vesting_contract_2) == operator_2_address, 5); } - #[test( - supra_framework = @0x1, - owner = @0x123, - operator_1 = @0x234, - operator_2 = @0x345, - new_operator = @0x567, - )] + #[ + test( + supra_framework = @0x1, + owner = @0x123, + operator_1 = @0x234, + operator_2 = @0x345, + new_operator = @0x567 + ) + ] public entry fun test_set_operator_nothing_to_change( supra_framework: &signer, owner: &signer, operator_1: &signer, operator_2: &signer, - new_operator: &signer, + new_operator: &signer ) { let owner_address = signer::address_of(owner); let operator_1_address = signer::address_of(operator_1); let operator_2_address = signer::address_of(operator_2); let new_operator_address = signer::address_of(new_operator); vesting::setup( - supra_framework, &vector[owner_address, operator_1_address, operator_2_address, new_operator_address]); - staking_contract::setup_staking_contract(supra_framework, owner, operator_2, INITIAL_BALANCE, 0); + supra_framework, + &vector[ + owner_address, + operator_1_address, + operator_2_address, + new_operator_address + ] + ); + staking_contract::setup_staking_contract( + supra_framework, owner, operator_2, INITIAL_BALANCE, 0 + ); - let vesting_contract_2 = vesting::setup_vesting_contract(owner, &vector[@12], &vector[INITIAL_BALANCE], owner_address, 0); + let vesting_contract_2 = + vesting::setup_vesting_contract( + owner, &vector[@12], &vector[INITIAL_BALANCE], owner_address, 0 + ); vesting::update_operator(owner, vesting_contract_2, operator_2_address, 0); set_operator(owner, operator_1_address, new_operator_address); // No staking or vesting contracts changed. - assert!(!staking_contract::staking_contract_exists(owner_address, new_operator_address), 0); - assert!(staking_contract::staking_contract_exists(owner_address, operator_2_address), 1); + assert!( + !staking_contract::staking_contract_exists( + owner_address, new_operator_address + ), + 0 + ); + assert!( + staking_contract::staking_contract_exists(owner_address, operator_2_address), + 1 + ); assert!(vesting::operator(vesting_contract_2) == operator_2_address, 2); } - #[test( - supra_framework = @0x1, - owner = @0x123, - operator_1 = @0x234, - operator_2 = @0x345, - new_voter = @0x567, - )] + #[ + test( + supra_framework = @0x1, + owner = @0x123, + operator_1 = @0x234, + operator_2 = @0x345, + new_voter = @0x567 + ) + ] public entry fun test_set_voter( supra_framework: &signer, owner: &signer, operator_1: &signer, operator_2: &signer, - new_voter: &signer, + new_voter: &signer ) { let owner_address = signer::address_of(owner); let operator_1_address = signer::address_of(operator_1); let operator_2_address = signer::address_of(operator_2); let new_voter_address = signer::address_of(new_voter); vesting::setup( - supra_framework, &vector[owner_address, operator_1_address, operator_2_address, new_voter_address]); - staking_contract::setup_staking_contract(supra_framework, owner, operator_1, INITIAL_BALANCE, 0); - staking_contract::setup_staking_contract(supra_framework, owner, operator_2, INITIAL_BALANCE, 0); + supra_framework, + &vector[ + owner_address, + operator_1_address, + operator_2_address, + new_voter_address + ] + ); + staking_contract::setup_staking_contract( + supra_framework, owner, operator_1, INITIAL_BALANCE, 0 + ); + staking_contract::setup_staking_contract( + supra_framework, owner, operator_2, INITIAL_BALANCE, 0 + ); - let vesting_contract_1 = vesting::setup_vesting_contract(owner, &vector[@11], &vector[INITIAL_BALANCE], owner_address, 0); + let vesting_contract_1 = + vesting::setup_vesting_contract( + owner, &vector[@11], &vector[INITIAL_BALANCE], owner_address, 0 + ); vesting::update_operator(owner, vesting_contract_1, operator_1_address, 0); - let vesting_contract_2 = vesting::setup_vesting_contract(owner, &vector[@12], &vector[INITIAL_BALANCE], owner_address, 0); + let vesting_contract_2 = + vesting::setup_vesting_contract( + owner, &vector[@12], &vector[INITIAL_BALANCE], owner_address, 0 + ); vesting::update_operator(owner, vesting_contract_2, operator_2_address, 0); let (_sk, pk) = stake::generate_identity(); - stake::initialize_test_validator(&pk, owner, INITIAL_BALANCE, false, false); + stake::initialize_test_validator(&pk, owner, INITIAL_BALANCE, false, false); set_voter(owner, operator_1_address, new_voter_address); // Stake pool's voter has been updated. assert!(stake::get_delegated_voter(owner_address) == new_voter_address, 0); // Staking contract with operator 1's voter has been updated. // Staking contract with operator_2 should stay unchanged. - let stake_pool_address_1 = staking_contract::stake_pool_address(owner_address, operator_1_address); - let stake_pool_address_2 = staking_contract::stake_pool_address(owner_address, operator_2_address); + let stake_pool_address_1 = + staking_contract::stake_pool_address(owner_address, operator_1_address); + let stake_pool_address_2 = + staking_contract::stake_pool_address(owner_address, operator_2_address); assert!(stake::get_delegated_voter(stake_pool_address_1) == new_voter_address, 1); assert!(stake::get_delegated_voter(stake_pool_address_2) == operator_2_address, 2); // Vesting contract 1's voter has been updated while vesting contract 2's stays unchanged. @@ -194,34 +296,49 @@ module supra_framework::staking_proxy { assert!(vesting::voter(vesting_contract_2) == owner_address, 4); } - #[test( - supra_framework = @0x1, - owner = @0x123, - operator_1 = @0x234, - operator_2 = @0x345, - new_voter = @0x567, - )] + #[ + test( + supra_framework = @0x1, + owner = @0x123, + operator_1 = @0x234, + operator_2 = @0x345, + new_voter = @0x567 + ) + ] public entry fun test_set_voter_nothing_to_change( supra_framework: &signer, owner: &signer, operator_1: &signer, operator_2: &signer, - new_voter: &signer, + new_voter: &signer ) { let owner_address = signer::address_of(owner); let operator_1_address = signer::address_of(operator_1); let operator_2_address = signer::address_of(operator_2); let new_voter_address = signer::address_of(new_voter); vesting::setup( - supra_framework, &vector[owner_address, operator_1_address, operator_2_address, new_voter_address]); - staking_contract::setup_staking_contract(supra_framework, owner, operator_2, INITIAL_BALANCE, 0); + supra_framework, + &vector[ + owner_address, + operator_1_address, + operator_2_address, + new_voter_address + ] + ); + staking_contract::setup_staking_contract( + supra_framework, owner, operator_2, INITIAL_BALANCE, 0 + ); - let vesting_contract_2 = vesting::setup_vesting_contract(owner, &vector[@12], &vector[INITIAL_BALANCE], owner_address, 0); + let vesting_contract_2 = + vesting::setup_vesting_contract( + owner, &vector[@12], &vector[INITIAL_BALANCE], owner_address, 0 + ); vesting::update_operator(owner, vesting_contract_2, operator_2_address, 0); set_operator(owner, operator_1_address, new_voter_address); // No staking or vesting contracts changed. - let stake_pool_address = staking_contract::stake_pool_address(owner_address, operator_2_address); + let stake_pool_address = + staking_contract::stake_pool_address(owner_address, operator_2_address); assert!(stake::get_delegated_voter(stake_pool_address) == operator_2_address, 0); assert!(vesting::voter(vesting_contract_2) == owner_address, 1); } diff --git a/aptos-move/framework/supra-framework/sources/staking_proxy.spec.move b/aptos-move/framework/supra-framework/sources/staking_proxy.spec.move index 22acbc7e51825..0ce25da9ee91f 100644 --- a/aptos-move/framework/supra-framework/sources/staking_proxy.spec.move +++ b/aptos-move/framework/supra-framework/sources/staking_proxy.spec.move @@ -62,12 +62,16 @@ spec supra_framework::staking_proxy { include SetStakePoolVoterAbortsIf; } - spec set_vesting_contract_operator(owner: &signer, old_operator: address, new_operator: address) { + spec set_vesting_contract_operator( + owner: &signer, old_operator: address, new_operator: address + ) { // TODO: Can't verify `update_voter` in while loop. pragma verify = false; } - spec set_staking_contract_operator(owner: &signer, old_operator: address, new_operator: address) { + spec set_staking_contract_operator( + owner: &signer, old_operator: address, new_operator: address + ) { pragma aborts_if_is_partial; pragma verify = false; // TODO: Verify timeout and can't verify `staking_contract::switch_operator`. @@ -85,11 +89,14 @@ spec supra_framework::staking_proxy { let owner_address = signer::address_of(owner); let store = global(owner_address); - let staking_contract_exists = exists(owner_address) && simple_map::spec_contains_key(store.staking_contracts, old_operator); - aborts_if staking_contract_exists && simple_map::spec_contains_key(store.staking_contracts, new_operator); + let staking_contract_exists = exists(owner_address) + && simple_map::spec_contains_key(store.staking_contracts, old_operator); + aborts_if staking_contract_exists + && simple_map::spec_contains_key(store.staking_contracts, new_operator); let post post_store = global(owner_address); - ensures staking_contract_exists ==> !simple_map::spec_contains_key(post_store.staking_contracts, old_operator); + ensures staking_contract_exists ==> + !simple_map::spec_contains_key(post_store.staking_contracts, old_operator); let staking_contract = simple_map::spec_get(store.staking_contracts, old_operator); let stake_pool = global(staking_contract.pool_address); @@ -97,20 +104,28 @@ spec supra_framework::staking_proxy { let pending_active = coin::value(stake_pool.pending_active); let total_active_stake = active + pending_active; let accumulated_rewards = total_active_stake - staking_contract.principal; - let commission_amount = accumulated_rewards * staking_contract.commission_percentage / 100; - aborts_if staking_contract_exists && !exists(staking_contract.pool_address); + let commission_amount = accumulated_rewards + * staking_contract.commission_percentage / 100; + aborts_if staking_contract_exists + && !exists(staking_contract.pool_address); // the following property caused timeout ensures staking_contract_exists ==> - simple_map::spec_get(post_store.staking_contracts, new_operator).principal == total_active_stake - commission_amount; + simple_map::spec_get(post_store.staking_contracts, new_operator).principal + == total_active_stake - commission_amount; let pool_address = staking_contract.owner_cap.pool_address; let current_commission_percentage = staking_contract.commission_percentage; - aborts_if staking_contract_exists && commission_amount != 0 && !exists(pool_address); - ensures staking_contract_exists && commission_amount != 0 ==> + aborts_if staking_contract_exists + && commission_amount != 0 + && !exists(pool_address); + ensures staking_contract_exists + && commission_amount != 0 ==> global(pool_address).operator_address == new_operator - && simple_map::spec_get(post_store.staking_contracts, new_operator).commission_percentage == current_commission_percentage; + && simple_map::spec_get(post_store.staking_contracts, new_operator).commission_percentage == + current_commission_percentage; - ensures staking_contract_exists ==> simple_map::spec_contains_key(post_store.staking_contracts, new_operator); + ensures staking_contract_exists ==> + simple_map::spec_contains_key(post_store.staking_contracts, new_operator); } spec set_vesting_contract_voter(owner: &signer, operator: address, new_voter: address) { @@ -131,8 +146,13 @@ spec supra_framework::staking_proxy { let owner_address = signer::address_of(owner); let ownership_cap = borrow_global(owner_address); let pool_address = ownership_cap.pool_address; - aborts_if stake::stake_pool_exists(owner_address) && !(exists(owner_address) && stake::stake_pool_exists(pool_address)); - ensures stake::stake_pool_exists(owner_address) ==> global(pool_address).operator_address == new_operator; + aborts_if stake::stake_pool_exists(owner_address) + && !( + exists(owner_address) + && stake::stake_pool_exists(pool_address) + ); + ensures stake::stake_pool_exists(owner_address) ==> + global(pool_address).operator_address == new_operator; } spec set_staking_contract_voter(owner: &signer, operator: address, new_voter: address) { @@ -152,16 +172,19 @@ spec supra_framework::staking_proxy { let owner_address = signer::address_of(owner); let staker = owner_address; let store = global(staker); - let staking_contract_exists = exists(staker) && simple_map::spec_contains_key(store.staking_contracts, operator); + let staking_contract_exists = exists(staker) + && simple_map::spec_contains_key(store.staking_contracts, operator); let staker_address = owner_address; let staking_contract = simple_map::spec_get(store.staking_contracts, operator); let pool_address = staking_contract.pool_address; let pool_address1 = staking_contract.owner_cap.pool_address; aborts_if staking_contract_exists && !exists(pool_address); - aborts_if staking_contract_exists && !exists(staking_contract.owner_cap.pool_address); + aborts_if staking_contract_exists + && !exists(staking_contract.owner_cap.pool_address); - ensures staking_contract_exists ==> global(pool_address1).delegated_voter == new_voter; + ensures staking_contract_exists ==> + global(pool_address1).delegated_voter == new_voter; } spec set_stake_pool_voter(owner: &signer, new_voter: address) { @@ -175,7 +198,12 @@ spec supra_framework::staking_proxy { let owner_address = signer::address_of(owner); let ownership_cap = global(owner_address); let pool_address = ownership_cap.pool_address; - aborts_if stake::stake_pool_exists(owner_address) && !(exists(owner_address) && stake::stake_pool_exists(pool_address)); - ensures stake::stake_pool_exists(owner_address) ==> global(pool_address).delegated_voter == new_voter; + aborts_if stake::stake_pool_exists(owner_address) + && !( + exists(owner_address) + && stake::stake_pool_exists(pool_address) + ); + ensures stake::stake_pool_exists(owner_address) ==> + global(pool_address).delegated_voter == new_voter; } } diff --git a/aptos-move/framework/supra-framework/sources/state_storage.move b/aptos-move/framework/supra-framework/sources/state_storage.move index 6a9b7572c2acf..554a992955004 100644 --- a/aptos-move/framework/supra-framework/sources/state_storage.move +++ b/aptos-move/framework/supra-framework/sources/state_storage.move @@ -11,14 +11,14 @@ module supra_framework::state_storage { struct Usage has copy, drop, store { items: u64, - bytes: u64, + bytes: u64 } /// This is updated at the beginning of each epoch, reflecting the storage /// usage after the last txn of the previous epoch is committed. struct StateStorageUsage has key, store { epoch: u64, - usage: Usage, + usage: Usage } public(friend) fun initialize(supra_framework: &signer) { @@ -27,13 +27,10 @@ module supra_framework::state_storage { !exists(@supra_framework), error::already_exists(ESTATE_STORAGE_USAGE) ); - move_to(supra_framework, StateStorageUsage { - epoch: 0, - usage: Usage { - items: 0, - bytes: 0, - } - }); + move_to( + supra_framework, + StateStorageUsage { epoch: 0, usage: Usage { items: 0, bytes: 0 } } + ); } public(friend) fun on_new_block(epoch: u64) acquires StateStorageUsage { @@ -71,17 +68,14 @@ module supra_framework::state_storage { ); let usage = borrow_global_mut(@supra_framework); usage.epoch = epoch; - usage.usage = Usage { - items, - bytes - }; + usage.usage = Usage { items, bytes }; } // ======================== deprecated ============================ friend supra_framework::reconfiguration; struct GasParameter has key, store { - usage: Usage, + usage: Usage } public(friend) fun on_reconfig() { diff --git a/aptos-move/framework/supra-framework/sources/state_storage.spec.move b/aptos-move/framework/supra-framework/sources/state_storage.spec.move index a397c05ffe710..8f461beeaddba 100644 --- a/aptos-move/framework/supra-framework/sources/state_storage.spec.move +++ b/aptos-move/framework/supra-framework/sources/state_storage.spec.move @@ -45,8 +45,10 @@ spec supra_framework::state_storage { // After genesis, `StateStorageUsage` and `GasParameter` exist. /// [high-level-req-1] /// [high-level-req-5.3] - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); } /// ensure caller is admin. @@ -61,7 +63,9 @@ spec supra_framework::state_storage { ensures exists(@supra_framework); let post state_usage = global(@supra_framework); /// [high-level-req-2] - ensures state_usage.epoch == 0 && state_usage.usage.bytes == 0 && state_usage.usage.items == 0; + ensures state_usage.epoch == 0 + && state_usage.usage.bytes == 0 + && state_usage.usage.items == 0; } spec on_new_block(epoch: u64) { diff --git a/aptos-move/framework/supra-framework/sources/storage_gas.move b/aptos-move/framework/supra-framework/sources/storage_gas.move index 31d9c10bdb95f..4d846619c4170 100644 --- a/aptos-move/framework/supra-framework/sources/storage_gas.move +++ b/aptos-move/framework/supra-framework/sources/storage_gas.move @@ -192,7 +192,7 @@ module supra_framework::storage_gas { /// Cost to create a byte in global storage. per_byte_create: u64, /// Cost to overwrite a byte in global storage. - per_byte_write: u64, + per_byte_write: u64 } /// A point in a Eulerian curve approximation, with each coordinate @@ -222,7 +222,7 @@ module supra_framework::storage_gas { target_usage: u64, read_curve: GasCurve, create_curve: GasCurve, - write_curve: GasCurve, + write_curve: GasCurve } /// Eulerian approximation of an exponential curve. @@ -247,7 +247,7 @@ module supra_framework::storage_gas { struct GasCurve has copy, drop, store { min_gas: u64, max_gas: u64, - points: vector, + points: vector } /// Default exponential curve having base 8192. @@ -298,19 +298,15 @@ module supra_framework::storage_gas { /// | 95% | 63.72% | /// | 99% | 91.38% | public fun base_8192_exponential_curve(min_gas: u64, max_gas: u64): GasCurve { - new_gas_curve(min_gas, max_gas, + new_gas_curve( + min_gas, + max_gas, vector[ - new_point(1000, 2), - new_point(2000, 6), - new_point(3000, 17), - new_point(4000, 44), - new_point(5000, 109), - new_point(6000, 271), - new_point(7000, 669), - new_point(8000, 1648), - new_point(9000, 4061), - new_point(9500, 6372), - new_point(9900, 9138), + new_point(1000, 2), new_point(2000, 6), new_point(3000, 17), new_point( + 4000, 44 + ), new_point(5000, 109), new_point(6000, 271), new_point(7000, 669), new_point( + 8000, 1648 + ), new_point(9000, 4061), new_point(9500, 6372), new_point(9900, 9138) ] ) } @@ -320,7 +316,7 @@ module supra_framework::storage_gas { /// Per-item gas configuration. item_config: UsageGasConfig, /// Per-byte gas configuration. - byte_config: UsageGasConfig, + byte_config: UsageGasConfig } public fun new_point(x: u64, y: u64): Point { @@ -331,36 +327,41 @@ module supra_framework::storage_gas { Point { x, y } } - public fun new_gas_curve(min_gas: u64, max_gas: u64, points: vector): GasCurve { + public fun new_gas_curve( + min_gas: u64, max_gas: u64, points: vector + ): GasCurve { assert!(max_gas >= min_gas, error::invalid_argument(EINVALID_GAS_RANGE)); - assert!(max_gas <= MAX_U64 / BASIS_POINT_DENOMINATION, error::invalid_argument(EINVALID_GAS_RANGE)); + assert!( + max_gas <= MAX_U64 / BASIS_POINT_DENOMINATION, + error::invalid_argument(EINVALID_GAS_RANGE) + ); validate_points(&points); - GasCurve { - min_gas, - max_gas, - points - } + GasCurve { min_gas, max_gas, points } } - public fun new_usage_gas_config(target_usage: u64, read_curve: GasCurve, create_curve: GasCurve, write_curve: GasCurve): UsageGasConfig { + public fun new_usage_gas_config( + target_usage: u64, + read_curve: GasCurve, + create_curve: GasCurve, + write_curve: GasCurve + ): UsageGasConfig { assert!(target_usage > 0, error::invalid_argument(EZERO_TARGET_USAGE)); - assert!(target_usage <= MAX_U64 / BASIS_POINT_DENOMINATION, error::invalid_argument(ETARGET_USAGE_TOO_BIG)); - UsageGasConfig { - target_usage, - read_curve, - create_curve, - write_curve, - } + assert!( + target_usage <= MAX_U64 / BASIS_POINT_DENOMINATION, + error::invalid_argument(ETARGET_USAGE_TOO_BIG) + ); + UsageGasConfig { target_usage, read_curve, create_curve, write_curve } } - public fun new_storage_gas_config(item_config: UsageGasConfig, byte_config: UsageGasConfig): StorageGasConfig { - StorageGasConfig { - item_config, - byte_config - } + public fun new_storage_gas_config( + item_config: UsageGasConfig, byte_config: UsageGasConfig + ): StorageGasConfig { + StorageGasConfig { item_config, byte_config } } - public(friend) fun set_config(supra_framework: &signer, config: StorageGasConfig) acquires StorageGasConfig { + public(friend) fun set_config( + supra_framework: &signer, config: StorageGasConfig + ) acquires StorageGasConfig { system_addresses::assert_supra_framework(supra_framework); *borrow_global_mut(@supra_framework) = config; } @@ -400,31 +401,34 @@ module supra_framework::storage_gas { target_usage: 2 * k * m, // 2 billion read_curve: base_8192_exponential_curve(300 * k, 300 * k * 100), create_curve: base_8192_exponential_curve(300 * k, 300 * k * 100), - write_curve: base_8192_exponential_curve(300 * k, 300 * k * 100), + write_curve: base_8192_exponential_curve(300 * k, 300 * k * 100) }; let byte_config = UsageGasConfig { target_usage: 1 * m * m, // 1TB read_curve: base_8192_exponential_curve(300, 300 * 100), - create_curve: base_8192_exponential_curve(5 * k, 5 * k * 100), - write_curve: base_8192_exponential_curve(5 * k, 5 * k * 100), + create_curve: base_8192_exponential_curve(5 * k, 5 * k * 100), + write_curve: base_8192_exponential_curve(5 * k, 5 * k * 100) }; - move_to(supra_framework, StorageGasConfig { - item_config, - byte_config, - }); + move_to( + supra_framework, + StorageGasConfig { item_config, byte_config } + ); assert!( !exists(@supra_framework), error::already_exists(ESTORAGE_GAS) ); - move_to(supra_framework, StorageGas { - per_item_read: 300 * k, - per_item_create: 5 * m, - per_item_write: 300 * k, - per_byte_read: 300, - per_byte_create: 5 * k, - per_byte_write: 5 * k, - }); + move_to( + supra_framework, + StorageGas { + per_item_read: 300 * k, + per_item_create: 5 * m, + per_item_write: 300 * k, + per_byte_read: 300, + per_byte_create: 5 * k, + per_byte_write: 5 * k + } + ); } fun validate_points(points: &vector) { @@ -435,64 +439,108 @@ module supra_framework::storage_gas { let i = 0; while ({ spec { - invariant forall j in 0..i: { - let cur = if (j == 0) { Point { x: 0, y: 0 } } else { points[j - 1] }; - let next = if (j == len) { Point { x: BASIS_POINT_DENOMINATION, y: BASIS_POINT_DENOMINATION } } else { points[j] }; - cur.x < next.x && cur.y <= next.y - }; + invariant forall j in 0..i: + { + let cur = if (j == 0) { + Point { x: 0, y: 0 } + } else { + points[j - 1] + }; + let next = + if (j == len) { + Point { + x: BASIS_POINT_DENOMINATION, + y: BASIS_POINT_DENOMINATION + } + } else { + points[j] + }; + cur.x < next.x && cur.y <= next.y + }; }; i <= len }) { - let cur = if (i == 0) { &Point { x: 0, y: 0 } } else { vector::borrow(points, i - 1) }; - let next = if (i == len) { &Point { x: BASIS_POINT_DENOMINATION, y: BASIS_POINT_DENOMINATION } } else { vector::borrow(points, i) }; - assert!(cur.x < next.x && cur.y <= next.y, error::invalid_argument(EINVALID_MONOTONICALLY_NON_DECREASING_CURVE)); + let cur = if (i == 0) { + &Point { x: 0, y: 0 } + } else { + vector::borrow(points, i - 1) + }; + let next = + if (i == len) { + &Point { x: BASIS_POINT_DENOMINATION, y: BASIS_POINT_DENOMINATION } + } else { + vector::borrow(points, i) + }; + assert!( + cur.x < next.x && cur.y <= next.y, + error::invalid_argument(EINVALID_MONOTONICALLY_NON_DECREASING_CURVE) + ); i = i + 1; } } - fun calculate_gas(max_usage: u64, current_usage: u64, curve: &GasCurve): u64 { - let capped_current_usage = if (current_usage > max_usage) max_usage else current_usage; + fun calculate_gas( + max_usage: u64, current_usage: u64, curve: &GasCurve + ): u64 { + let capped_current_usage = if (current_usage > max_usage) max_usage + else current_usage; let points = &curve.points; let num_points = vector::length(points); - let current_usage_bps = capped_current_usage * BASIS_POINT_DENOMINATION / max_usage; + let current_usage_bps = capped_current_usage * BASIS_POINT_DENOMINATION + / max_usage; // Check the corner case that current_usage_bps drops before the first point. - let (left, right) = if (num_points == 0) { - (&Point { x: 0, y: 0 }, &Point { x: BASIS_POINT_DENOMINATION, y: BASIS_POINT_DENOMINATION }) - } else if (current_usage_bps < vector::borrow(points, 0).x) { - (&Point { x: 0, y: 0 }, vector::borrow(points, 0)) - } else if (vector::borrow(points, num_points - 1).x <= current_usage_bps) { - (vector::borrow(points, num_points - 1), &Point { x: BASIS_POINT_DENOMINATION, y: BASIS_POINT_DENOMINATION }) - } else { - let (i, j) = (0, num_points - 2); - while ({ - spec { - invariant i <= j; - invariant j < num_points - 1; - invariant points[i].x <= current_usage_bps; - invariant current_usage_bps < points[j + 1].x; - }; - i < j - }) { - let mid = j - (j - i) / 2; - if (current_usage_bps < vector::borrow(points, mid).x) { + let (left, right) = + if (num_points == 0) { + ( + &Point { x: 0, y: 0 }, + &Point { x: BASIS_POINT_DENOMINATION, y: BASIS_POINT_DENOMINATION } + ) + } else if (current_usage_bps < vector::borrow(points, 0).x) { + (&Point { x: 0, y: 0 }, vector::borrow(points, 0)) + } else if (vector::borrow(points, num_points - 1).x <= current_usage_bps) { + ( + vector::borrow(points, num_points - 1), + &Point { x: BASIS_POINT_DENOMINATION, y: BASIS_POINT_DENOMINATION } + ) + } else { + let (i, j) = (0, num_points - 2); + while ({ spec { - // j is strictly decreasing. - assert mid - 1 < j; + invariant i <= j; + invariant j < num_points - 1; + invariant points[i].x <= current_usage_bps; + invariant current_usage_bps < points[j + 1].x; }; - j = mid - 1; - } else { - spec { - // i is strictly increasing. - assert i < mid; + i < j + }) { + let mid = j - (j - i) / 2; + if (current_usage_bps < vector::borrow(points, mid).x) { + spec { + // j is strictly decreasing. + assert mid - 1 < j; + }; + j = mid - 1; + } else { + spec { + // i is strictly increasing. + assert i < mid; + }; + i = mid; }; - i = mid; }; + (vector::borrow(points, i), vector::borrow(points, i + 1)) }; - (vector::borrow(points, i), vector::borrow(points, i + 1)) - }; - let y_interpolated = interpolate(left.x, right.x, left.y, right.y, current_usage_bps); - interpolate(0, BASIS_POINT_DENOMINATION, curve.min_gas, curve.max_gas, y_interpolated) + let y_interpolated = interpolate( + left.x, right.x, left.y, right.y, current_usage_bps + ); + interpolate( + 0, + BASIS_POINT_DENOMINATION, + curve.min_gas, + curve.max_gas, + y_interpolated + ) } // Interpolates y for x on the line between (x0, y0) and (x1, y1). @@ -559,7 +607,17 @@ module supra_framework::storage_gas { let old_standard_curve_gas = 1; while (i <= target + 7) { assert!(calculate_gas(target, i, &constant_curve) == 5, 0); - assert!(calculate_gas(target, i, &linear_curve) == (if (i < target) { 1 + 999 * (i * BASIS_POINT_DENOMINATION / target) / BASIS_POINT_DENOMINATION } else { 1000 }), 0); + assert!( + calculate_gas(target, i, &linear_curve) + == ( + if (i < target) { + 1 + + 999 * (i * BASIS_POINT_DENOMINATION / target) + / BASIS_POINT_DENOMINATION + } else { 1000 } + ), + 0 + ); let new_standard_curve_gas = calculate_gas(target, i, &standard_curve); assert!(new_standard_curve_gas >= old_standard_curve_gas, 0); old_standard_curve_gas = new_standard_curve_gas; @@ -574,13 +632,20 @@ module supra_framework::storage_gas { fun test_set_storage_gas_config(framework: signer) acquires StorageGas, StorageGasConfig { state_storage::initialize(&framework); initialize(&framework); - let item_curve = new_gas_curve(1000, 2000, - vector[new_point(3000, 0), new_point(5000, 5000), new_point(8000, 5000)] - ); - let byte_curve = new_gas_curve(0, 1000, vector::singleton(new_point(5000, 3000))); - let item_usage_config = new_usage_gas_config(100, copy item_curve, copy item_curve, copy item_curve); - let byte_usage_config = new_usage_gas_config(2000, copy byte_curve, copy byte_curve, copy byte_curve); - let storage_gas_config = new_storage_gas_config(item_usage_config, byte_usage_config); + let item_curve = + new_gas_curve( + 1000, + 2000, + vector[new_point(3000, 0), new_point(5000, 5000), new_point(8000, 5000)] + ); + let byte_curve = + new_gas_curve(0, 1000, vector::singleton(new_point(5000, 3000))); + let item_usage_config = + new_usage_gas_config(100, copy item_curve, copy item_curve, copy item_curve); + let byte_usage_config = + new_usage_gas_config(2000, copy byte_curve, copy byte_curve, copy byte_curve); + let storage_gas_config = + new_storage_gas_config(item_usage_config, byte_usage_config); set_config(&framework, storage_gas_config); { state_storage::set_for_test(0, 20, 100); diff --git a/aptos-move/framework/supra-framework/sources/storage_gas.spec.move b/aptos-move/framework/supra-framework/sources/storage_gas.spec.move index 90a6681734ed5..dbbcc2c7b1cbc 100644 --- a/aptos-move/framework/supra-framework/sources/storage_gas.spec.move +++ b/aptos-move/framework/supra-framework/sources/storage_gas.spec.move @@ -16,8 +16,13 @@ spec supra_framework::storage_gas { /// Invariant 3: The x-coordinate increases monotonically and the y-coordinate increasing strictly monotonically, /// that is, the gas-curve is a monotonically increasing function. invariant (len(points) > 0 ==> points[0].x > 0) - && (len(points) > 0 ==> points[len(points) - 1].x < BASIS_POINT_DENOMINATION) - && (forall i in 0..len(points) - 1: (points[i].x < points[i + 1].x && points[i].y <= points[i + 1].y)); + && (len(points) > 0 ==> + points[len(points) - 1].x < BASIS_POINT_DENOMINATION) + && ( + forall i in 0..len(points) - 1: + (points[i].x < points[i + 1].x + && points[i].y <= points[i + 1].y) + ); } spec UsageGasConfig { @@ -25,7 +30,6 @@ spec supra_framework::storage_gas { invariant target_usage <= MAX_U64 / BASIS_POINT_DENOMINATION; } - // ----------------- // Global invariants // ----------------- @@ -66,11 +70,12 @@ spec supra_framework::storage_gas { pragma verify = true; pragma aborts_if_is_strict; // After genesis, `StateStorageUsage` and `GasParameter` exist. - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); } - // ----------------------- // Function specifications // ----------------------- @@ -92,23 +97,20 @@ spec supra_framework::storage_gas { include NewGasCurveAbortsIf; include ValidatePointsAbortsIf; /// [high-level-req-3] - ensures result == GasCurve { - min_gas, - max_gas, - points - }; + ensures result == GasCurve { min_gas, max_gas, points }; } - spec new_usage_gas_config(target_usage: u64, read_curve: GasCurve, create_curve: GasCurve, write_curve: GasCurve): UsageGasConfig { + spec new_usage_gas_config( + target_usage: u64, + read_curve: GasCurve, + create_curve: GasCurve, + write_curve: GasCurve + ): UsageGasConfig { aborts_if target_usage == 0; aborts_if target_usage > MAX_U64 / BASIS_POINT_DENOMINATION; /// [high-level-req-4] - ensures result == UsageGasConfig { - target_usage, - read_curve, - create_curve, - write_curve, - }; + ensures result + == UsageGasConfig { target_usage, read_curve, create_curve, write_curve }; } spec new_storage_gas_config(item_config: UsageGasConfig, byte_config: UsageGasConfig): StorageGasConfig { @@ -120,7 +122,7 @@ spec supra_framework::storage_gas { /// Signer address must be @supra_framework and StorageGasConfig exists. spec set_config(supra_framework: &signer, config: StorageGasConfig) { - include system_addresses::AbortsIfNotAptosFramework{ account: supra_framework }; + include system_addresses::AbortsIfNotAptosFramework { account: supra_framework }; aborts_if !exists(@supra_framework); } @@ -128,7 +130,7 @@ spec supra_framework::storage_gas { /// Address @supra_framework does not exist StorageGasConfig and StorageGas before the function call is restricted /// and exists after the function is executed. spec initialize(supra_framework: &signer) { - include system_addresses::AbortsIfNotAptosFramework{ account: supra_framework }; + include system_addresses::AbortsIfNotAptosFramework { account: supra_framework }; pragma verify_duration_estimate = 120; aborts_if exists(@supra_framework); aborts_if exists(@supra_framework); @@ -153,10 +155,13 @@ spec supra_framework::storage_gas { requires max_usage > 0; requires max_usage <= MAX_U64 / BASIS_POINT_DENOMINATION; aborts_if false; - ensures [abstract] result == spec_calculate_gas(max_usage, current_usage, curve); + ensures [abstract] result + == spec_calculate_gas(max_usage, current_usage, curve); } - spec interpolate(x0: u64, x1: u64, y0: u64, y1: u64, x: u64): u64 { + spec interpolate( + x0: u64, x1: u64, y0: u64, y1: u64, x: u64 + ): u64 { pragma opaque; pragma intrinsic; @@ -172,7 +177,6 @@ spec supra_framework::storage_gas { aborts_if !exists(@supra_framework); } - // --------------------------------- // Spec helper functions and schemas // --------------------------------- @@ -192,10 +196,10 @@ spec supra_framework::storage_gas { points: vector; /// [high-level-req-2] - aborts_if exists i in 0..len(points) - 1: ( - points[i].x >= points[i + 1].x || points[i].y > points[i + 1].y - ); + aborts_if exists i in 0..len(points) - 1: + (points[i].x >= points[i + 1].x || points[i].y > points[i + 1].y); aborts_if len(points) > 0 && points[0].x == 0; - aborts_if len(points) > 0 && points[len(points) - 1].x == BASIS_POINT_DENOMINATION; + aborts_if len(points) > 0 + && points[len(points) - 1].x == BASIS_POINT_DENOMINATION; } } diff --git a/aptos-move/framework/supra-framework/sources/supra_account.move b/aptos-move/framework/supra-framework/sources/supra_account.move index a5f475d4e9ab2..19ff160e66a4c 100644 --- a/aptos-move/framework/supra-framework/sources/supra_account.move +++ b/aptos-move/framework/supra-framework/sources/supra_account.move @@ -33,18 +33,18 @@ module supra_framework::supra_account { /// By default, this is enabled. Users can opt-out by disabling at any time. struct DirectTransferConfig has key { allow_arbitrary_coin_transfers: bool, - update_coin_transfer_events: EventHandle, + update_coin_transfer_events: EventHandle } /// Event emitted when an account's direct coins transfer config is updated. struct DirectCoinTransferConfigUpdatedEvent has drop, store { - new_allow_direct_transfers: bool, + new_allow_direct_transfers: bool } #[event] struct DirectCoinTransferConfigUpdated has drop, store { account: address, - new_allow_direct_transfers: bool, + new_allow_direct_transfers: bool } /////////////////////////////////////////////////////////////////////////// @@ -57,17 +57,22 @@ module supra_framework::supra_account { } /// Batch version of SUPRA transfer. - public entry fun batch_transfer(source: &signer, recipients: vector
, amounts: vector) { + public entry fun batch_transfer( + source: &signer, recipients: vector
, amounts: vector + ) { let recipients_len = vector::length(&recipients); assert!( recipients_len == vector::length(&amounts), - error::invalid_argument(EMISMATCHING_RECIPIENTS_AND_AMOUNTS_LENGTH), + error::invalid_argument(EMISMATCHING_RECIPIENTS_AND_AMOUNTS_LENGTH) ); - vector::enumerate_ref(&recipients, |i, to| { - let amount = *vector::borrow(&amounts, i); - transfer(source, *to, amount); - }); + vector::enumerate_ref( + &recipients, + |i, to| { + let amount = *vector::borrow(&amounts, i); + transfer(source, *to, amount); + } + ); } /// Convenient function to transfer SUPRA to a recipient account that might not exist. @@ -91,40 +96,49 @@ module supra_framework::supra_account { /// Batch version of transfer_coins. public entry fun batch_transfer_coins( - from: &signer, recipients: vector
, amounts: vector) acquires DirectTransferConfig { + from: &signer, recipients: vector
, amounts: vector + ) acquires DirectTransferConfig { let recipients_len = vector::length(&recipients); assert!( recipients_len == vector::length(&amounts), - error::invalid_argument(EMISMATCHING_RECIPIENTS_AND_AMOUNTS_LENGTH), + error::invalid_argument(EMISMATCHING_RECIPIENTS_AND_AMOUNTS_LENGTH) ); - vector::enumerate_ref(&recipients, |i, to| { - let amount = *vector::borrow(&amounts, i); - transfer_coins(from, *to, amount); - }); + vector::enumerate_ref( + &recipients, + |i, to| { + let amount = *vector::borrow(&amounts, i); + transfer_coins(from, *to, amount); + } + ); } /// Convenient function to transfer a custom CoinType to a recipient account that might not exist. /// This would create the recipient account first and register it to receive the CoinType, before transferring. - public entry fun transfer_coins(from: &signer, to: address, amount: u64) acquires DirectTransferConfig { + public entry fun transfer_coins( + from: &signer, to: address, amount: u64 + ) acquires DirectTransferConfig { deposit_coins(to, coin::withdraw(from, amount)); } /// Convenient function to deposit a custom CoinType into a recipient account that might not exist. /// This would create the recipient account first and register it to receive the CoinType, before transferring. - public fun deposit_coins(to: address, coins: Coin) acquires DirectTransferConfig { + public fun deposit_coins( + to: address, coins: Coin + ) acquires DirectTransferConfig { if (!account::exists_at(to)) { create_account(to); spec { assert coin::spec_is_account_registered(to); - assume aptos_std::type_info::type_of() == aptos_std::type_info::type_of() ==> + assume aptos_std::type_info::type_of() + == aptos_std::type_info::type_of() ==> coin::spec_is_account_registered(to); }; }; if (!coin::is_account_registered(to)) { assert!( can_receive_direct_coin_transfers(to), - error::permission_denied(EACCOUNT_DOES_NOT_ACCEPT_DIRECT_COIN_TRANSFERS), + error::permission_denied(EACCOUNT_DOES_NOT_ACCEPT_DIRECT_COIN_TRANSFERS) ); coin::register(&create_signer(to)); }; @@ -137,38 +151,54 @@ module supra_framework::supra_account { public fun assert_account_is_registered_for_supra(addr: address) { assert_account_exists(addr); - assert!(coin::is_account_registered(addr), error::not_found(EACCOUNT_NOT_REGISTERED_FOR_SUPRA)); + assert!( + coin::is_account_registered(addr), + error::not_found(EACCOUNT_NOT_REGISTERED_FOR_SUPRA) + ); } /// Set whether `account` can receive direct transfers of coins that they have not explicitly registered to receive. - public entry fun set_allow_direct_coin_transfers(account: &signer, allow: bool) acquires DirectTransferConfig { + public entry fun set_allow_direct_coin_transfers( + account: &signer, allow: bool + ) acquires DirectTransferConfig { let addr = signer::address_of(account); if (exists(addr)) { let direct_transfer_config = borrow_global_mut(addr); // Short-circuit to avoid emitting an event if direct transfer config is not changing. - if (direct_transfer_config.allow_arbitrary_coin_transfers == allow) { - return - }; + if (direct_transfer_config.allow_arbitrary_coin_transfers == allow) { return }; direct_transfer_config.allow_arbitrary_coin_transfers = allow; if (std::features::module_event_migration_enabled()) { - emit(DirectCoinTransferConfigUpdated { account: addr, new_allow_direct_transfers: allow }); + emit( + DirectCoinTransferConfigUpdated { + account: addr, + new_allow_direct_transfers: allow + } + ); }; emit_event( &mut direct_transfer_config.update_coin_transfer_events, - DirectCoinTransferConfigUpdatedEvent { new_allow_direct_transfers: allow }); + DirectCoinTransferConfigUpdatedEvent { new_allow_direct_transfers: allow } + ); } else { let direct_transfer_config = DirectTransferConfig { allow_arbitrary_coin_transfers: allow, - update_coin_transfer_events: new_event_handle(account), + update_coin_transfer_events: new_event_handle< + DirectCoinTransferConfigUpdatedEvent>(account) }; if (std::features::module_event_migration_enabled()) { - emit(DirectCoinTransferConfigUpdated { account: addr, new_allow_direct_transfers: allow }); + emit( + DirectCoinTransferConfigUpdated { + account: addr, + new_allow_direct_transfers: allow + } + ); }; emit_event( &mut direct_transfer_config.update_coin_transfer_events, - DirectCoinTransferConfigUpdatedEvent { new_allow_direct_transfers: allow }); + DirectCoinTransferConfigUpdatedEvent { new_allow_direct_transfers: allow } + ); move_to(account, direct_transfer_config); }; } @@ -178,9 +208,11 @@ module supra_framework::supra_account { /// receive. /// /// By default, this returns true if an account has not explicitly set whether the can receive direct transfers. - public fun can_receive_direct_coin_transfers(account: address): bool acquires DirectTransferConfig { - !exists(account) || - borrow_global(account).allow_arbitrary_coin_transfers + public fun can_receive_direct_coin_transfers( + account: address + ): bool acquires DirectTransferConfig { + !exists(account) + || borrow_global(account).allow_arbitrary_coin_transfers } public(friend) fun register_supra(account_signer: &signer) { @@ -201,7 +233,8 @@ module supra_framework::supra_account { fun fungible_transfer_only( source: &signer, to: address, amount: u64 ) { - let sender_store = ensure_primary_fungible_store_exists(signer::address_of(source)); + let sender_store = + ensure_primary_fungible_store_exists(signer::address_of(source)); let recipient_store = ensure_primary_fungible_store_exists(to); // use internal APIs, as they skip: @@ -209,11 +242,15 @@ module supra_framework::supra_account { // as SUPRA cannot be frozen or have dispatch, and PFS cannot be transfered // (PFS could potentially be burned. regular transfer would permanently unburn the store. // Ignoring the check here has the equivalent of unburning, transfers, and then burning again) - fungible_asset::deposit_internal(recipient_store, fungible_asset::withdraw_internal(sender_store, amount)); + fungible_asset::deposit_internal( + recipient_store, fungible_asset::withdraw_internal(sender_store, amount) + ); } /// Is balance from SUPRA Primary FungibleStore at least the given amount - public(friend) fun is_fungible_balance_at_least(account: address, amount: u64): bool { + public(friend) fun is_fungible_balance_at_least( + account: address, amount: u64 + ): bool { let store_addr = primary_fungible_store_address(account); fungible_asset::is_address_balance_at_least(store_addr, amount) } @@ -222,7 +259,7 @@ module supra_framework::supra_account { public(friend) fun burn_from_fungible_store( ref: &BurnRef, account: address, - amount: u64, + amount: u64 ) { // Skip burning if amount is zero. This shouldn't error out as it's called as part of transaction fee burning. if (amount != 0) { @@ -237,7 +274,11 @@ module supra_framework::supra_account { if (fungible_asset::store_exists(store_addr)) { store_addr } else { - object::object_address(&primary_fungible_store::create_primary_store(owner, object::address_to_object(@aptos_fungible_asset))) + object::object_address( + &primary_fungible_store::create_primary_store( + owner, object::address_to_object(@aptos_fungible_asset) + ) + ) } } @@ -260,8 +301,14 @@ module supra_framework::supra_account { #[test(alice = @0xa11ce, core = @0x1)] public fun test_transfer(alice: &signer, core: &signer) { - let bob = from_bcs::to_address(x"0000000000000000000000000000000000000000000000000000000000000b0b"); - let carol = from_bcs::to_address(x"00000000000000000000000000000000000000000000000000000000000ca501"); + let bob = + from_bcs::to_address( + x"0000000000000000000000000000000000000000000000000000000000000b0b" + ); + let carol = + from_bcs::to_address( + x"00000000000000000000000000000000000000000000000000000000000ca501" + ); let (burn_cap, mint_cap) = supra_framework::supra_coin::initialize_for_test(core); create_account(signer::address_of(alice)); @@ -278,7 +325,9 @@ module supra_framework::supra_account { } #[test(alice = @0xa11ce, core = @0x1)] - public fun test_transfer_to_resource_account(alice: &signer, core: &signer) { + public fun test_transfer_to_resource_account( + alice: &signer, core: &signer + ) { let (resource_account, _) = account::create_resource_account(alice, vector[]); let resource_acc_addr = signer::address_of(&resource_account); let (burn_cap, mint_cap) = supra_framework::supra_coin::initialize_for_test(core); @@ -293,8 +342,15 @@ module supra_framework::supra_account { coin::destroy_mint_cap(mint_cap); } - #[test(from = @0x123, core = @0x1, recipient_1 = @0x124, recipient_2 = @0x125)] - public fun test_batch_transfer(from: &signer, core: &signer, recipient_1: &signer, recipient_2: &signer) { + #[test( + from = @0x123, core = @0x1, recipient_1 = @0x124, recipient_2 = @0x125 + )] + public fun test_batch_transfer( + from: &signer, + core: &signer, + recipient_1: &signer, + recipient_2: &signer + ) { let (burn_cap, mint_cap) = supra_framework::supra_coin::initialize_for_test(core); create_account(signer::address_of(from)); let recipient_1_addr = signer::address_of(recipient_1); @@ -305,7 +361,7 @@ module supra_framework::supra_account { batch_transfer( from, vector[recipient_1_addr, recipient_2_addr], - vector[100, 500], + vector[100, 500] ); assert!(coin::balance(recipient_1_addr) == 100, 0); assert!(coin::balance(recipient_2_addr) == 500, 1); @@ -315,13 +371,14 @@ module supra_framework::supra_account { #[test(from = @0x1, to = @0x12)] public fun test_direct_coin_transfers(from: &signer, to: &signer) acquires DirectTransferConfig { - let (burn_cap, freeze_cap, mint_cap) = coin::initialize( - from, - utf8(b"FC"), - utf8(b"FC"), - 10, - true, - ); + let (burn_cap, freeze_cap, mint_cap) = + coin::initialize( + from, + utf8(b"FC"), + utf8(b"FC"), + 10, + true + ); create_account_for_test(signer::address_of(from)); create_account_for_test(signer::address_of(to)); deposit_coins(signer::address_of(from), coin::mint(1000, &mint_cap)); @@ -337,14 +394,16 @@ module supra_framework::supra_account { #[test(from = @0x1, recipient_1 = @0x124, recipient_2 = @0x125)] public fun test_batch_transfer_coins( - from: &signer, recipient_1: &signer, recipient_2: &signer) acquires DirectTransferConfig { - let (burn_cap, freeze_cap, mint_cap) = coin::initialize( - from, - utf8(b"FC"), - utf8(b"FC"), - 10, - true, - ); + from: &signer, recipient_1: &signer, recipient_2: &signer + ) acquires DirectTransferConfig { + let (burn_cap, freeze_cap, mint_cap) = + coin::initialize( + from, + utf8(b"FC"), + utf8(b"FC"), + 10, + true + ); create_account_for_test(signer::address_of(from)); let recipient_1_addr = signer::address_of(recipient_1); let recipient_2_addr = signer::address_of(recipient_2); @@ -354,7 +413,7 @@ module supra_framework::supra_account { batch_transfer_coins( from, vector[recipient_1_addr, recipient_2_addr], - vector[100, 500], + vector[100, 500] ); assert!(coin::balance(recipient_1_addr) == 100, 0); assert!(coin::balance(recipient_2_addr) == 500, 1); @@ -378,14 +437,16 @@ module supra_framework::supra_account { #[test(from = @0x1, to = @0x12)] public fun test_direct_coin_transfers_with_explicit_direct_coin_transfer_config( - from: &signer, to: &signer) acquires DirectTransferConfig { - let (burn_cap, freeze_cap, mint_cap) = coin::initialize( - from, - utf8(b"FC"), - utf8(b"FC"), - 10, - true, - ); + from: &signer, to: &signer + ) acquires DirectTransferConfig { + let (burn_cap, freeze_cap, mint_cap) = + coin::initialize( + from, + utf8(b"FC"), + utf8(b"FC"), + 10, + true + ); create_account_for_test(signer::address_of(from)); create_account_for_test(signer::address_of(to)); set_allow_direct_coin_transfers(from, true); @@ -403,14 +464,16 @@ module supra_framework::supra_account { #[test(from = @0x1, to = @0x12)] #[expected_failure(abort_code = 0x50003, location = Self)] public fun test_direct_coin_transfers_fail_if_recipient_opted_out( - from: &signer, to: &signer) acquires DirectTransferConfig { - let (burn_cap, freeze_cap, mint_cap) = coin::initialize( - from, - utf8(b"FC"), - utf8(b"FC"), - 10, - true, - ); + from: &signer, to: &signer + ) acquires DirectTransferConfig { + let (burn_cap, freeze_cap, mint_cap) = + coin::initialize( + from, + utf8(b"FC"), + utf8(b"FC"), + 10, + true + ); create_account_for_test(signer::address_of(from)); create_account_for_test(signer::address_of(to)); set_allow_direct_coin_transfers(from, false); @@ -424,9 +487,7 @@ module supra_framework::supra_account { } #[test(user = @0xcafe)] - fun test_primary_fungible_store_address( - user: &signer, - ) { + fun test_primary_fungible_store_address(user: &signer) { use supra_framework::fungible_asset::Metadata; use supra_framework::supra_coin; @@ -434,7 +495,11 @@ module supra_framework::supra_account { let apt_metadata = object::address_to_object(@aptos_fungible_asset); let user_addr = signer::address_of(user); - assert!(primary_fungible_store_address(user_addr) == primary_fungible_store::primary_store_address(user_addr, apt_metadata), 1); + assert!( + primary_fungible_store_address(user_addr) + == primary_fungible_store::primary_store_address(user_addr, apt_metadata), + 1 + ); ensure_primary_fungible_store_exists(user_addr); assert!(primary_fungible_store::primary_store_exists(user_addr, apt_metadata), 2); diff --git a/aptos-move/framework/supra-framework/sources/supra_account.spec.move b/aptos-move/framework/supra-framework/sources/supra_account.spec.move index 84e2e0a99823b..6ccfd430fa6c0 100644 --- a/aptos-move/framework/supra-framework/sources/supra_account.spec.move +++ b/aptos-move/framework/supra-framework/sources/supra_account.spec.move @@ -71,11 +71,14 @@ spec supra_framework::supra_account { include CreateAccountAbortsIf; ensures exists(auth_key); } + spec schema CreateAccountAbortsIf { auth_key: address; aborts_if exists(auth_key); aborts_if length_judgment(auth_key); - aborts_if auth_key == @vm_reserved || auth_key == @supra_framework || auth_key == @aptos_token; + aborts_if auth_key == @vm_reserved + || auth_key == @supra_framework + || auth_key == @aptos_token; } spec fun length_judgment(auth_key: address): bool { @@ -95,10 +98,11 @@ spec supra_framework::supra_account { include CreateAccountTransferAbortsIf; include GuidAbortsIf; - include WithdrawAbortsIf{from: source}; + include WithdrawAbortsIf { from: source }; include TransferEnsures; - aborts_if exists>(to) && global>(to).frozen; + aborts_if exists>(to) + && global>(to).frozen; /// [high-level-req-5] ensures exists(to); ensures exists>(to); @@ -131,50 +135,71 @@ spec supra_framework::supra_account { let coin_store_source = global>(account_addr_source); let balance_source = coin_store_source.coin.value; - requires forall i in 0..len(recipients): - recipients[i] != account_addr_source; - requires exists i in 0..len(recipients): - amounts[i] > 0; + requires forall i in 0..len(recipients): recipients[i] != account_addr_source; + requires exists i in 0..len(recipients): amounts[i] > 0; // create account properties aborts_if len(recipients) != len(amounts); aborts_if exists i in 0..len(recipients): - !account::exists_at(recipients[i]) && length_judgment(recipients[i]); + !account::exists_at(recipients[i]) && length_judgment(recipients[i]); aborts_if exists i in 0..len(recipients): - !account::exists_at(recipients[i]) && (recipients[i] == @vm_reserved || recipients[i] == @supra_framework || recipients[i] == @aptos_token); + !account::exists_at(recipients[i]) + && ( + recipients[i] == @vm_reserved + || recipients[i] == @supra_framework + || recipients[i] == @aptos_token + ); ensures forall i in 0..len(recipients): - (!account::exists_at(recipients[i]) ==> !length_judgment(recipients[i])) && - (!account::exists_at(recipients[i]) ==> (recipients[i] != @vm_reserved && recipients[i] != @supra_framework && recipients[i] != @aptos_token)); + (!account::exists_at(recipients[i]) ==> + !length_judgment(recipients[i])) + && ( + !account::exists_at(recipients[i]) ==> + ( + recipients[i] != @vm_reserved + && recipients[i] != @supra_framework + && recipients[i] != @aptos_token + ) + ); // coin::withdraw properties aborts_if exists i in 0..len(recipients): !exists>(account_addr_source); + aborts_if exists i in 0..len(recipients): coin_store_source.frozen; aborts_if exists i in 0..len(recipients): - coin_store_source.frozen; - aborts_if exists i in 0..len(recipients): - global>(account_addr_source).coin.value < amounts[i]; + global>(account_addr_source).coin.value + < amounts[i]; // deposit properties aborts_if exists i in 0..len(recipients): - exists>(recipients[i]) && global>(recipients[i]).frozen; + exists>(recipients[i]) + && global>(recipients[i]).frozen; // guid properties aborts_if exists i in 0..len(recipients): - account::exists_at(recipients[i]) && !exists>(recipients[i]) && global(recipients[i]).guid_creation_num + 2 >= account::MAX_GUID_CREATION_NUM; + account::exists_at(recipients[i]) + && !exists>(recipients[i]) + && global(recipients[i]).guid_creation_num + 2 + >= account::MAX_GUID_CREATION_NUM; aborts_if exists i in 0..len(recipients): - account::exists_at(recipients[i]) && !exists>(recipients[i]) && global(recipients[i]).guid_creation_num + 2 > MAX_U64; + account::exists_at(recipients[i]) + && !exists>(recipients[i]) + && global(recipients[i]).guid_creation_num + 2 + > MAX_U64; } spec can_receive_direct_coin_transfers(account: address): bool { aborts_if false; /// [high-level-req-3] - ensures result == ( - !exists(account) || - global(account).allow_arbitrary_coin_transfers - ); + ensures result + == ( + !exists(account) + || global(account).allow_arbitrary_coin_transfers + ); } - spec batch_transfer_coins(from: &signer, recipients: vector
, amounts: vector) { + spec batch_transfer_coins( + from: &signer, recipients: vector
, amounts: vector + ) { //TODO: Can't verify the loop invariant in enumerate use aptos_std::type_info; pragma verify = false; @@ -182,45 +207,64 @@ spec supra_framework::supra_account { let coin_store_source = global>(account_addr_source); let balance_source = coin_store_source.coin.value; - requires forall i in 0..len(recipients): - recipients[i] != account_addr_source; + requires forall i in 0..len(recipients): recipients[i] != account_addr_source; - requires exists i in 0..len(recipients): - amounts[i] > 0; + requires exists i in 0..len(recipients): amounts[i] > 0; /// [high-level-req-7] aborts_if len(recipients) != len(amounts); //create account properties aborts_if exists i in 0..len(recipients): - !account::exists_at(recipients[i]) && length_judgment(recipients[i]); + !account::exists_at(recipients[i]) && length_judgment(recipients[i]); aborts_if exists i in 0..len(recipients): - !account::exists_at(recipients[i]) && (recipients[i] == @vm_reserved || recipients[i] == @supra_framework || recipients[i] == @aptos_token); + !account::exists_at(recipients[i]) + && ( + recipients[i] == @vm_reserved + || recipients[i] == @supra_framework + || recipients[i] == @aptos_token + ); ensures forall i in 0..len(recipients): - (!account::exists_at(recipients[i]) ==> !length_judgment(recipients[i])) && - (!account::exists_at(recipients[i]) ==> (recipients[i] != @vm_reserved && recipients[i] != @supra_framework && recipients[i] != @aptos_token)); + (!account::exists_at(recipients[i]) ==> + !length_judgment(recipients[i])) + && ( + !account::exists_at(recipients[i]) ==> + ( + recipients[i] != @vm_reserved + && recipients[i] != @supra_framework + && recipients[i] != @aptos_token + ) + ); // coin::withdraw properties aborts_if exists i in 0..len(recipients): !exists>(account_addr_source); + aborts_if exists i in 0..len(recipients): coin_store_source.frozen; aborts_if exists i in 0..len(recipients): - coin_store_source.frozen; - aborts_if exists i in 0..len(recipients): - global>(account_addr_source).coin.value < amounts[i]; + global>(account_addr_source).coin.value + < amounts[i]; // deposit properties aborts_if exists i in 0..len(recipients): - exists>(recipients[i]) && global>(recipients[i]).frozen; + exists>(recipients[i]) + && global>(recipients[i]).frozen; // guid properties aborts_if exists i in 0..len(recipients): - account::exists_at(recipients[i]) && !exists>(recipients[i]) && global(recipients[i]).guid_creation_num + 2 >= account::MAX_GUID_CREATION_NUM; + account::exists_at(recipients[i]) + && !exists>(recipients[i]) + && global(recipients[i]).guid_creation_num + 2 + >= account::MAX_GUID_CREATION_NUM; aborts_if exists i in 0..len(recipients): - account::exists_at(recipients[i]) && !exists>(recipients[i]) && global(recipients[i]).guid_creation_num + 2 > MAX_U64; + account::exists_at(recipients[i]) + && !exists>(recipients[i]) + && global(recipients[i]).guid_creation_num + 2 + > MAX_U64; // register_coin properties aborts_if exists i in 0..len(recipients): - !coin::spec_is_account_registered(recipients[i]) && !type_info::spec_is_struct(); + !coin::spec_is_account_registered(recipients[i]) + && !type_info::spec_is_struct(); } spec deposit_coins(to: address, coins: Coin) { @@ -238,7 +282,8 @@ spec supra_framework::supra_account { let coin_store_to = global>(to).coin.value; let post post_coin_store_to = global>(to).coin.value; - ensures if_exist_coin ==> post_coin_store_to == coin_store_to + coins.value; + ensures if_exist_coin ==> + post_coin_store_to == coin_store_to + coins.value; } spec transfer_coins(from: &signer, to: address, amount: u64) { @@ -255,7 +300,8 @@ spec supra_framework::supra_account { include RegistCoinAbortsIf; include TransferEnsures; - aborts_if exists>(to) && global>(to).frozen; + aborts_if exists>(to) + && global>(to).frozen; ensures exists(to); ensures exists>(to); } @@ -276,9 +322,7 @@ spec supra_framework::supra_account { } spec burn_from_fungible_store( - ref: &BurnRef, - account: address, - amount: u64, + ref: &BurnRef, account: address, amount: u64 ) { // TODO: temporary mockup. pragma verify = false; @@ -287,7 +331,10 @@ spec supra_framework::supra_account { spec schema CreateAccountTransferAbortsIf { to: address; aborts_if !account::exists_at(to) && length_judgment(to); - aborts_if !account::exists_at(to) && (to == @vm_reserved || to == @supra_framework || to == @aptos_token); + aborts_if !account::exists_at(to) + && (to == @vm_reserved + || to == @supra_framework + || to == @aptos_token); } spec schema WithdrawAbortsIf { @@ -304,14 +351,19 @@ spec supra_framework::supra_account { spec schema GuidAbortsIf { to: address; let acc = global(to); - aborts_if account::exists_at(to) && !exists>(to) && acc.guid_creation_num + 2 >= account::MAX_GUID_CREATION_NUM; - aborts_if account::exists_at(to) && !exists>(to) && acc.guid_creation_num + 2 > MAX_U64; + aborts_if account::exists_at(to) + && !exists>(to) + && acc.guid_creation_num + 2 >= account::MAX_GUID_CREATION_NUM; + aborts_if account::exists_at(to) + && !exists>(to) + && acc.guid_creation_num + 2 > MAX_U64; } spec schema RegistCoinAbortsIf { use aptos_std::type_info; to: address; - aborts_if !coin::spec_is_account_registered(to) && !type_info::spec_is_struct(); + aborts_if !coin::spec_is_account_registered(to) + && !type_info::spec_is_struct(); aborts_if exists(to); aborts_if type_info::type_of() != type_info::type_of(); } @@ -326,8 +378,11 @@ spec supra_framework::supra_account { let coin_store_to = global>(to); let coin_store_source = global>(account_addr_source); let post p_coin_store_to = global>(to); - let post p_coin_store_source = global>(account_addr_source); + let post p_coin_store_source = global>( + account_addr_source + ); ensures coin_store_source.coin.value - amount == p_coin_store_source.coin.value; - ensures if_exist_account && if_exist_coin ==> coin_store_to.coin.value + amount == p_coin_store_to.coin.value; + ensures if_exist_account && if_exist_coin ==> + coin_store_to.coin.value + amount == p_coin_store_to.coin.value; } } diff --git a/aptos-move/framework/supra-framework/sources/supra_coin.move b/aptos-move/framework/supra-framework/sources/supra_coin.move index c17b12749c6e1..ae3882785bfb8 100644 --- a/aptos-move/framework/supra-framework/sources/supra_coin.move +++ b/aptos-move/framework/supra-framework/sources/supra_coin.move @@ -12,10 +12,9 @@ module supra_framework::supra_coin { friend supra_framework::genesis; - - /// Max supply of Supra Coin to be 100 billion with 8 decimal places fraction - const MAX_SUPRA_COIN_SUPPLY: u128 = 100_000_000_000_00_000_000u128; - //const MAX_SUPRA_COIN_SUPPLY: u128 = 340282366920938463463374607431768211455u128; + /// Max supply of Supra Coin to be 100 billion with 8 decimal places fraction + const MAX_SUPRA_COIN_SUPPLY: u128 = 100_000_000_000_00_000_000u128; + //const MAX_SUPRA_COIN_SUPPLY: u128 = 340282366920938463463374607431768211455u128; /// Account does not have mint capability const ENO_CAPABILITIES: u64 = 1; /// Mint capability has already been delegated to this specified address @@ -26,7 +25,7 @@ module supra_framework::supra_coin { struct SupraCoin has key {} struct MintCapStore has key { - mint_cap: MintCapability, + mint_cap: MintCapability } /// Delegation token created by delegator and can be claimed by the delegatee as MintCapability. @@ -36,21 +35,24 @@ module supra_framework::supra_coin { /// The container stores the current pending delegations. struct Delegations has key { - inner: vector, + inner: vector } /// Can only called during genesis to initialize the Supra coin. - public(friend) fun initialize(supra_framework: &signer): (BurnCapability, MintCapability) { + public(friend) fun initialize( + supra_framework: &signer + ): (BurnCapability, MintCapability) { system_addresses::assert_supra_framework(supra_framework); - let (burn_cap, freeze_cap, mint_cap) =coin::initialize_with_parallelizable_supply_with_limit( - supra_framework, - string::utf8(b"Supra Coin"), - string::utf8(b"SUPRA"), - 8, // decimals - true, // monitor_supply - MAX_SUPRA_COIN_SUPPLY, - ); + let (burn_cap, freeze_cap, mint_cap) = + coin::initialize_with_parallelizable_supply_with_limit( + supra_framework, + string::utf8(b"Supra Coin"), + string::utf8(b"SUPRA"), + 8, // decimals + true, // monitor_supply + MAX_SUPRA_COIN_SUPPLY + ); // Supra framework needs mint cap to mint coins to initial validators. This will be revoked once the validators // have been initialized. @@ -78,14 +80,14 @@ module supra_framework::supra_coin { public(friend) fun configure_accounts_for_test( supra_framework: &signer, core_resources: &signer, - mint_cap: MintCapability, + mint_cap: MintCapability ) { system_addresses::assert_supra_framework(supra_framework); // Mint the core resource account SupraCoin for gas so it can execute system transactions. let coins = coin::mint( - ((MAX_SUPRA_COIN_SUPPLY)/10 as u64), - &mint_cap, + ((MAX_SUPRA_COIN_SUPPLY) / 10 as u64), + &mint_cap ); coin::deposit(signer::address_of(core_resources), coins); @@ -98,13 +100,13 @@ module supra_framework::supra_coin { public entry fun mint( account: &signer, dst_addr: address, - amount: u64, + amount: u64 ) acquires MintCapStore { let account_addr = signer::address_of(account); assert!( exists(account_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let mint_cap = &borrow_global(account_addr).mint_cap; @@ -117,10 +119,13 @@ module supra_framework::supra_coin { public entry fun delegate_mint_capability(account: signer, to: address) acquires Delegations { system_addresses::assert_core_resource(&account); let delegations = &mut borrow_global_mut(@core_resources).inner; - vector::for_each_ref(delegations, |element| { - let element: &DelegatedMintCapability = element; - assert!(element.to != to, error::invalid_argument(EALREADY_DELEGATED)); - }); + vector::for_each_ref( + delegations, + |element| { + let element: &DelegatedMintCapability = element; + assert!(element.to != to, error::invalid_argument(EALREADY_DELEGATED)); + } + ); vector::push_back(delegations, DelegatedMintCapability { to }); } @@ -177,7 +182,9 @@ module supra_framework::supra_coin { let supra_framework = account::create_signer_for_test(@supra_framework); if (!exists(@supra_framework)) { if (!aggregator_factory::aggregator_factory_exists_for_testing()) { - aggregator_factory::initialize_aggregator_factory_for_test(&supra_framework); + aggregator_factory::initialize_aggregator_factory_for_test( + &supra_framework + ); }; let (burn_cap, mint_cap) = initialize(&supra_framework); coin::destroy_burn_cap(burn_cap); @@ -188,7 +195,9 @@ module supra_framework::supra_coin { } #[test_only] - public fun initialize_for_test(supra_framework: &signer): (BurnCapability, MintCapability) { + public fun initialize_for_test( + supra_framework: &signer + ): (BurnCapability, MintCapability) { aggregator_factory::initialize_aggregator_factory_for_test(supra_framework); let (burn_cap, mint_cap) = initialize(supra_framework); coin::create_coin_conversion_map(supra_framework); @@ -198,19 +207,20 @@ module supra_framework::supra_coin { #[test_only] fun initialize_with_aggregator(supra_framework: &signer) { - let (burn_cap, freeze_cap, mint_cap) =coin::initialize_with_parallelizable_supply_with_limit( + let (burn_cap, freeze_cap, mint_cap) = + coin::initialize_with_parallelizable_supply_with_limit( + supra_framework, + string::utf8(b"Supra Coin"), + string::utf8(b"SUPRA"), + 8, // decimals + true, // monitor_supply + MAX_SUPRA_COIN_SUPPLY + ); + coin::destroy_freeze_cap(freeze_cap); + move_to( supra_framework, - string::utf8(b"Supra Coin"), - string::utf8(b"SUPRA"), - 8, // decimals - true, // monitor_supply - MAX_SUPRA_COIN_SUPPLY, + SupraCoinCapabilities { burn_cap, mint_cap } ); - coin::destroy_freeze_cap(freeze_cap); - move_to(supra_framework, SupraCoinCapabilities { - burn_cap, - mint_cap, - }); } // This is particularly useful if the aggregator_factory is already initialized via another call path. @@ -227,14 +237,11 @@ module supra_framework::supra_coin { #[test_only] struct SupraCoinCapabilities has key { burn_cap: BurnCapability, - mint_cap: MintCapability, + mint_cap: MintCapability } - #[test(source = @0x1, destination = @0x2)] - public entry fun end_to_end( - source: signer, - destination: signer, - ) { + #[test(source = @0x1, destination = @0x2)] + public entry fun end_to_end(source: signer, destination: signer) { let source_addr = signer::address_of(&source); account::create_account_for_test(source_addr); let destination_addr = signer::address_of(&destination); @@ -244,9 +251,7 @@ module supra_framework::supra_coin { let symbol = string::utf8(b"SUPRA"); aggregator_factory::initialize_aggregator_factory_for_test(&source); - let (burn_cap, mint_cap) = initialize( - &source, - ); + let (burn_cap, mint_cap) = initialize(&source); coin::register(&source); coin::register(&destination); assert!(*option::borrow(&coin::supply()) == 0, 0); @@ -268,54 +273,52 @@ module supra_framework::supra_coin { coin::burn(coin, &burn_cap); assert!(*option::borrow(&coin::supply()) == 90, 8); - move_to(&source, SupraCoinCapabilities { - burn_cap, - mint_cap, - }); + move_to( + &source, + SupraCoinCapabilities { burn_cap, mint_cap } + ); } #[test(source = @0x1, destination = @0x2)] public entry fun test_mint_no_overflow( - source: signer, - destination: signer, - ){ + source: signer, destination: signer + ) { let source_addr = signer::address_of(&source); account::create_account_for_test(source_addr); let destination_addr = signer::address_of(&destination); account::create_account_for_test(destination_addr); aggregator_factory::initialize_aggregator_factory_for_test(&source); - let (burn_cap, mint_cap) = initialize( - &source, - ); + let (burn_cap, mint_cap) = initialize(&source); coin::register(&source); coin::register(&destination); assert!(*option::borrow(&coin::supply()) == 0, 0); assert!(*option::borrow(&coin::supply()) == 0, 0); - let coins_minted = coin::mint((MAX_SUPRA_COIN_SUPPLY as u64), &mint_cap); + let coins_minted = coin::mint( + (MAX_SUPRA_COIN_SUPPLY as u64), &mint_cap + ); coin::deposit(source_addr, coins_minted); - coin::transfer(&source, destination_addr, (MAX_SUPRA_COIN_SUPPLY as u64)); + coin::transfer( + &source, destination_addr, (MAX_SUPRA_COIN_SUPPLY as u64) + ); coin::destroy_burn_cap(burn_cap); coin::destroy_mint_cap(mint_cap); } #[test(source = @0x1)] #[expected_failure(abort_code = 0x20001, location = supra_framework::aggregator)] - public entry fun test_mint_overflow( - source: signer, - ) { + public entry fun test_mint_overflow(source: signer) { let source_addr = signer::address_of(&source); account::create_account_for_test(source_addr); aggregator_factory::initialize_aggregator_factory_for_test(&source); - let (burn_cap, mint_cap) = initialize( - &source, - ); + let (burn_cap, mint_cap) = initialize(&source); coin::register(&source); assert!(*option::borrow(&coin::supply()) == 0, 0); - let coins_minted = coin::mint((MAX_SUPRA_COIN_SUPPLY as u64)+1, &mint_cap); + let coins_minted = + coin::mint((MAX_SUPRA_COIN_SUPPLY as u64) + 1, &mint_cap); coin::deposit(source_addr, coins_minted); coin::destroy_burn_cap(burn_cap); coin::destroy_mint_cap(mint_cap); diff --git a/aptos-move/framework/supra-framework/sources/supra_coin.spec.move b/aptos-move/framework/supra-framework/sources/supra_coin.spec.move index 5adefa0d5beaf..df03e109abbaf 100644 --- a/aptos-move/framework/supra-framework/sources/supra_coin.spec.move +++ b/aptos-move/framework/supra-framework/sources/supra_coin.spec.move @@ -4,7 +4,9 @@ spec supra_framework::supra_coin { pragma aborts_if_is_strict; } - spec initialize(supra_framework: &signer): (BurnCapability, MintCapability) { + spec initialize(supra_framework: &signer): ( + BurnCapability, MintCapability + ) { use supra_framework::aggregator_factory; let addr = signer::address_of(supra_framework); @@ -33,9 +35,7 @@ spec supra_framework::supra_coin { // Only callable in tests and testnets. not needed verify. spec mint( - account: &signer, - dst_addr: address, - amount: u64, + account: &signer, dst_addr: address, amount: u64 ) { pragma verify = false; } @@ -57,5 +57,4 @@ spec supra_framework::supra_coin { spec schema ExistsSupraCoin { requires exists>(@supra_framework); } - } diff --git a/aptos-move/framework/supra-framework/sources/supra_governance.move b/aptos-move/framework/supra-framework/sources/supra_governance.move index 88592a19eb49b..71a26cbd3e81c 100644 --- a/aptos-move/framework/supra-framework/sources/supra_governance.move +++ b/aptos-move/framework/supra-framework/sources/supra_governance.move @@ -57,13 +57,13 @@ module supra_framework::supra_governance { /// Store the SignerCapabilities of accounts under the on-chain governance's control. struct GovernanceResponsbility has key { - signer_caps: SimpleMap, + signer_caps: SimpleMap } /// Used to track which execution script hashes have been approved by governance. /// This is required to bypass cases where the execution scripts exceed the size limit imposed by mempool. struct ApprovedExecutionHashes has key { - hashes: SimpleMap>, + hashes: SimpleMap> } /// Configurations of the SupraGovernance, set during Genesis and can be updated by the same process offered @@ -71,14 +71,14 @@ module supra_framework::supra_governance { struct SupraGovernanceConfig has key { voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector
, + voters: vector
} /// Events generated by interactions with the SupraGovernance module. struct SupraGovernanceEvents has key { create_proposal_events: EventHandle, update_config_events: EventHandle, - vote_events: EventHandle, + vote_events: EventHandle } /// Event emitted when a proposal is created. @@ -86,21 +86,21 @@ module supra_framework::supra_governance { proposer: address, proposal_id: u64, execution_hash: vector, - proposal_metadata: SimpleMap>, + proposal_metadata: SimpleMap> } /// Event emitted when the governance configs are updated. struct SupraUpdateConfigEvent has drop, store { voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector
, + voters: vector
} /// Event emitted when there's a vote on a proposa; struct SupraVoteEvent has drop, store { proposal_id: u64, voter: address, - should_pass: bool, + should_pass: bool } #[event] @@ -109,7 +109,7 @@ module supra_framework::supra_governance { proposer: address, proposal_id: u64, execution_hash: vector, - proposal_metadata: SimpleMap>, + proposal_metadata: SimpleMap> } #[event] @@ -117,7 +117,7 @@ module supra_framework::supra_governance { struct SupraVote has drop, store { proposal_id: u64, voter: address, - should_pass: bool, + should_pass: bool } #[event] @@ -125,7 +125,7 @@ module supra_framework::supra_governance { struct SupraUpdateConfig has drop, store { voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector
, + voters: vector
} /// Can be called during genesis or by the governance itself. @@ -133,7 +133,7 @@ module supra_framework::supra_governance { public fun store_signer_cap( supra_framework: &signer, signer_address: address, - signer_cap: SignerCapability, + signer_cap: SignerCapability ) acquires GovernanceResponsbility { system_addresses::assert_supra_framework(supra_framework); system_addresses::assert_framework_reserved(signer_address); @@ -141,11 +141,14 @@ module supra_framework::supra_governance { if (!exists(@supra_framework)) { move_to( supra_framework, - GovernanceResponsbility { signer_caps: simple_map::create() } + GovernanceResponsbility { + signer_caps: simple_map::create() + } ); }; - let signer_caps = &mut borrow_global_mut(@supra_framework).signer_caps; + let signer_caps = + &mut borrow_global_mut(@supra_framework).signer_caps; simple_map::add(signer_caps, signer_address, signer_cap); } @@ -156,26 +159,42 @@ module supra_framework::supra_governance { supra_framework: &signer, voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector
, + voters: vector
) { multisig_voting::register(supra_framework); - assert!(vector::length(&voters) >= min_voting_threshold && min_voting_threshold > vector::length(&voters) / 2, error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS)); - assert!(min_voting_threshold > 1, error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE)); + assert!( + vector::length(&voters) >= min_voting_threshold + && min_voting_threshold > vector::length(&voters) / 2, + error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS) + ); + assert!( + min_voting_threshold > 1, + error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE) + ); - move_to(supra_framework, SupraGovernanceConfig { - voting_duration_secs, - min_voting_threshold, - voters, - }); - move_to(supra_framework, SupraGovernanceEvents { - create_proposal_events: account::new_event_handle(supra_framework), - update_config_events: account::new_event_handle(supra_framework), - vote_events: account::new_event_handle(supra_framework), - }); - move_to(supra_framework, ApprovedExecutionHashes { - hashes: simple_map::create>(), - }) + move_to( + supra_framework, + SupraGovernanceConfig { voting_duration_secs, min_voting_threshold, voters } + ); + move_to( + supra_framework, + SupraGovernanceEvents { + create_proposal_events: account::new_event_handle( + supra_framework + ), + update_config_events: account::new_event_handle( + supra_framework + ), + vote_events: account::new_event_handle(supra_framework) + } + ); + move_to( + supra_framework, + ApprovedExecutionHashes { + hashes: simple_map::create>() + } + ) } /// Update the governance configurations. This can only be called as part of resolving a proposal in this same @@ -184,35 +203,35 @@ module supra_framework::supra_governance { supra_framework: &signer, voting_duration_secs: u64, min_voting_threshold: u64, - voters: vector
, + voters: vector
) acquires SupraGovernanceConfig, SupraGovernanceEvents { system_addresses::assert_supra_framework(supra_framework); - assert!(vector::length(&voters) >= min_voting_threshold && min_voting_threshold > vector::length(&voters) / 2, error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS)); - assert!(min_voting_threshold > 1, error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE)); + assert!( + vector::length(&voters) >= min_voting_threshold + && min_voting_threshold > vector::length(&voters) / 2, + error::invalid_argument(ETHRESHOLD_EXCEEDS_VOTERS) + ); + assert!( + min_voting_threshold > 1, + error::invalid_argument(ETHRESHOLD_MUST_BE_GREATER_THAN_ONE) + ); - let supra_governance_config = borrow_global_mut(@supra_framework); + let supra_governance_config = + borrow_global_mut(@supra_framework); supra_governance_config.voting_duration_secs = voting_duration_secs; supra_governance_config.min_voting_threshold = min_voting_threshold; supra_governance_config.voters = voters; if (std::features::module_event_migration_enabled()) { event::emit( - SupraUpdateConfig { - min_voting_threshold, - voting_duration_secs, - voters, - }, + SupraUpdateConfig { min_voting_threshold, voting_duration_secs, voters } ) }; let events = borrow_global_mut(@supra_framework); event::emit_event( &mut events.update_config_events, - SupraUpdateConfigEvent { - min_voting_threshold, - voting_duration_secs, - voters, - }, + SupraUpdateConfigEvent { min_voting_threshold, voting_duration_secs, voters } ); } @@ -238,9 +257,11 @@ module supra_framework::supra_governance { proposer: &signer, execution_hash: vector, metadata_location: vector, - metadata_hash: vector, + metadata_hash: vector ) acquires SupraGovernanceConfig, SupraGovernanceEvents { - supra_create_proposal_v2(proposer, execution_hash, metadata_location, metadata_hash, false); + supra_create_proposal_v2( + proposer, execution_hash, metadata_location, metadata_hash, false + ); } /// Create a single-step or multi-step proposal with the backing `stake_pool`. @@ -251,7 +272,7 @@ module supra_framework::supra_governance { execution_hash: vector, metadata_location: vector, metadata_hash: vector, - is_multi_step_proposal: bool, + is_multi_step_proposal: bool ) acquires SupraGovernanceConfig, SupraGovernanceEvents { supra_create_proposal_v2_impl( proposer, @@ -271,29 +292,35 @@ module supra_framework::supra_governance { execution_hash: vector, metadata_location: vector, metadata_hash: vector, - is_multi_step_proposal: bool, + is_multi_step_proposal: bool ): u64 acquires SupraGovernanceConfig, SupraGovernanceEvents { let proposer_address = signer::address_of(proposer); - let supra_governance_config = borrow_global(@supra_framework); + let supra_governance_config = + borrow_global(@supra_framework); - assert!(vector::contains(&supra_governance_config.voters, &proposer_address), error::permission_denied(EACCOUNT_NOT_AUTHORIZED)); + assert!( + vector::contains(&supra_governance_config.voters, &proposer_address), + error::permission_denied(EACCOUNT_NOT_AUTHORIZED) + ); - let proposal_expiration = timestamp::now_seconds() + supra_governance_config.voting_duration_secs; + let proposal_expiration = + timestamp::now_seconds() + supra_governance_config.voting_duration_secs; // Create and validate proposal metadata. let proposal_metadata = create_proposal_metadata(metadata_location, metadata_hash); - let proposal_id = multisig_voting::create_proposal_v2( - proposer_address, - @supra_framework, - governance_proposal::create_proposal(), - execution_hash, - supra_governance_config.min_voting_threshold, - supra_governance_config.voters, - proposal_expiration, - proposal_metadata, - is_multi_step_proposal, - ); + let proposal_id = + multisig_voting::create_proposal_v2( + proposer_address, + @supra_framework, + governance_proposal::create_proposal(), + execution_hash, + supra_governance_config.min_voting_threshold, + supra_governance_config.voters, + proposal_expiration, + proposal_metadata, + is_multi_step_proposal + ); if (std::features::module_event_migration_enabled()) { event::emit( @@ -301,8 +328,8 @@ module supra_framework::supra_governance { proposal_id, proposer: proposer_address, execution_hash, - proposal_metadata, - }, + proposal_metadata + } ); }; let events = borrow_global_mut(@supra_framework); @@ -312,8 +339,8 @@ module supra_framework::supra_governance { proposal_id, proposer: proposer_address, execution_hash, - proposal_metadata, - }, + proposal_metadata + } ); proposal_id } @@ -322,7 +349,7 @@ module supra_framework::supra_governance { public entry fun supra_vote( voter: &signer, proposal_id: u64, - should_pass: bool, + should_pass: bool ) acquires ApprovedExecutionHashes, SupraGovernanceEvents, SupraGovernanceConfig { supra_vote_internal(voter, proposal_id, should_pass); } @@ -334,54 +361,58 @@ module supra_framework::supra_governance { fun supra_vote_internal( voter: &signer, proposal_id: u64, - should_pass: bool, + should_pass: bool ) acquires ApprovedExecutionHashes, SupraGovernanceEvents, SupraGovernanceConfig { let voter_address = signer::address_of(voter); - let supra_governance_config = borrow_global(@supra_framework); - assert!(vector::contains(&supra_governance_config.voters, &signer::address_of(voter)), error::permission_denied(EACCOUNT_NOT_AUTHORIZED)); + let supra_governance_config = + borrow_global(@supra_framework); + assert!( + vector::contains(&supra_governance_config.voters, &signer::address_of(voter)), + error::permission_denied(EACCOUNT_NOT_AUTHORIZED) + ); // The voter's stake needs to be locked up at least as long as the proposal's expiration. - let proposal_expiration = multisig_voting::get_proposal_expiration_secs( - @supra_framework, - proposal_id + let proposal_expiration = + multisig_voting::get_proposal_expiration_secs( + @supra_framework, proposal_id + ); + assert!( + timestamp::now_seconds() <= proposal_expiration, + error::invalid_argument(EPROPOSAL_IS_EXPIRE) ); - assert!(timestamp::now_seconds() <= proposal_expiration, error::invalid_argument(EPROPOSAL_IS_EXPIRE)); multisig_voting::vote( voter, &governance_proposal::create_empty_proposal(), @supra_framework, proposal_id, - should_pass, + should_pass ); if (std::features::module_event_migration_enabled()) { event::emit( - SupraVote { - proposal_id, - voter: voter_address, - should_pass, - }, + SupraVote { proposal_id, voter: voter_address, should_pass } ); }; let events = borrow_global_mut(@supra_framework); event::emit_event( &mut events.vote_events, - SupraVoteEvent { - proposal_id, - voter: voter_address, - should_pass, - }, + SupraVoteEvent { proposal_id, voter: voter_address, should_pass } ); - let proposal_state = multisig_voting::get_proposal_state(@supra_framework, proposal_id); + let proposal_state = + multisig_voting::get_proposal_state( + @supra_framework, proposal_id + ); if (proposal_state == PROPOSAL_STATE_SUCCEEDED) { add_supra_approved_script_hash(proposal_id); } } - public entry fun add_supra_approved_script_hash_script(proposal_id: u64) acquires ApprovedExecutionHashes { + public entry fun add_supra_approved_script_hash_script( + proposal_id: u64 + ) acquires ApprovedExecutionHashes { add_supra_approved_script_hash(proposal_id) } @@ -389,18 +420,29 @@ module supra_framework::supra_governance { /// This is needed to bypass the mempool transaction size limit for approved governance proposal transactions that /// are too large (e.g. module upgrades). public fun add_supra_approved_script_hash(proposal_id: u64) acquires ApprovedExecutionHashes { - let approved_hashes = borrow_global_mut(@supra_framework); + let approved_hashes = + borrow_global_mut(@supra_framework); // Ensure the proposal can be resolved. - let proposal_state = multisig_voting::get_proposal_state(@supra_framework, proposal_id); - assert!(proposal_state == PROPOSAL_STATE_SUCCEEDED, error::invalid_argument(EPROPOSAL_NOT_RESOLVABLE_YET)); + let proposal_state = + multisig_voting::get_proposal_state( + @supra_framework, proposal_id + ); + assert!( + proposal_state == PROPOSAL_STATE_SUCCEEDED, + error::invalid_argument(EPROPOSAL_NOT_RESOLVABLE_YET) + ); - let execution_hash = multisig_voting::get_execution_hash(@supra_framework, proposal_id); + let execution_hash = + multisig_voting::get_execution_hash( + @supra_framework, proposal_id + ); // If this is a multi-step proposal, the proposal id will already exist in the ApprovedExecutionHashes map. // We will update execution hash in ApprovedExecutionHashes to be the next_execution_hash. if (simple_map::contains_key(&approved_hashes.hashes, &proposal_id)) { - let current_execution_hash = simple_map::borrow_mut(&mut approved_hashes.hashes, &proposal_id); + let current_execution_hash = + simple_map::borrow_mut(&mut approved_hashes.hashes, &proposal_id); *current_execution_hash = execution_hash; } else { simple_map::add(&mut approved_hashes.hashes, proposal_id, execution_hash); @@ -410,8 +452,7 @@ module supra_framework::supra_governance { /// Resolve a successful single-step proposal. This would fail if the proposal is not successful (not enough votes or more no /// than yes). public fun supra_resolve( - proposal_id: u64, - signer_address: address + proposal_id: u64, signer_address: address ): signer acquires ApprovedExecutionHashes, GovernanceResponsbility { multisig_voting::resolve(@supra_framework, proposal_id); remove_supra_approved_hash(proposal_id); @@ -420,11 +461,11 @@ module supra_framework::supra_governance { /// Resolve a successful multi-step proposal. This would fail if the proposal is not successful. public fun resolve_supra_multi_step_proposal( - proposal_id: u64, - signer_address: address, - next_execution_hash: vector + proposal_id: u64, signer_address: address, next_execution_hash: vector ): signer acquires GovernanceResponsbility, ApprovedExecutionHashes { - multisig_voting::resolve_proposal_v2(@supra_framework, proposal_id, next_execution_hash); + multisig_voting::resolve_proposal_v2( + @supra_framework, proposal_id, next_execution_hash + ); // If the current step is the last step of this multi-step proposal, // we will remove the execution hash from the ApprovedExecutionHashes map. if (vector::length(&next_execution_hash) == 0) { @@ -441,11 +482,14 @@ module supra_framework::supra_governance { /// Remove an approved proposal's execution script hash. public fun remove_supra_approved_hash(proposal_id: u64) acquires ApprovedExecutionHashes { assert!( - multisig_voting::is_resolved(@supra_framework, proposal_id), - error::invalid_argument(EPROPOSAL_NOT_RESOLVED_YET), + multisig_voting::is_resolved( + @supra_framework, proposal_id + ), + error::invalid_argument(EPROPOSAL_NOT_RESOLVED_YET) ); - let approved_hashes = &mut borrow_global_mut(@supra_framework).hashes; + let approved_hashes = + &mut borrow_global_mut(@supra_framework).hashes; if (simple_map::contains_key(approved_hashes, &proposal_id)) { simple_map::remove(approved_hashes, &proposal_id); }; @@ -482,14 +526,18 @@ module supra_framework::supra_governance { /// `force_end_epoch()` equivalent but only called in testnet, /// where the core resources account exists and has been granted power to mint Supra coins. - public entry fun force_end_epoch_test_only(supra_framework: &signer) acquires GovernanceResponsbility { + public entry fun force_end_epoch_test_only( + supra_framework: &signer + ) acquires GovernanceResponsbility { let core_signer = get_signer_testnet_only(supra_framework, @0x1); system_addresses::assert_supra_framework(&core_signer); reconfiguration_with_dkg::finish(&core_signer); } /// Update feature flags and also trigger reconfiguration. - public fun toggle_features(supra_framework: &signer, enable: vector, disable: vector) { + public fun toggle_features( + supra_framework: &signer, enable: vector, disable: vector + ) { system_addresses::assert_supra_framework(supra_framework); features::change_feature_flags_for_next_epoch(supra_framework, enable, disable); reconfigure(supra_framework); @@ -497,26 +545,37 @@ module supra_framework::supra_governance { /// Only called in testnet where the core resources account exists and has been granted power to mint Supra coins. public fun get_signer_testnet_only( - core_resources: &signer, signer_address: address): signer acquires GovernanceResponsbility { + core_resources: &signer, signer_address: address + ): signer acquires GovernanceResponsbility { system_addresses::assert_core_resource(core_resources); // Core resources account only has mint capability in tests/testnets. - assert!(supra_coin::has_mint_capability(core_resources), error::unauthenticated(EUNAUTHORIZED)); + assert!( + supra_coin::has_mint_capability(core_resources), + error::unauthenticated(EUNAUTHORIZED) + ); get_signer(signer_address) } /// Return a signer for making changes to 0x1 as part of on-chain governance proposal process. fun get_signer(signer_address: address): signer acquires GovernanceResponsbility { - let governance_responsibility = borrow_global(@supra_framework); - let signer_cap = simple_map::borrow(&governance_responsibility.signer_caps, &signer_address); + let governance_responsibility = + borrow_global(@supra_framework); + let signer_cap = + simple_map::borrow(&governance_responsibility.signer_caps, &signer_address); create_signer_with_capability(signer_cap) } fun create_proposal_metadata( - metadata_location: vector, - metadata_hash: vector + metadata_location: vector, metadata_hash: vector ): SimpleMap> { - assert!(string::length(&utf8(metadata_location)) <= 256, error::invalid_argument(EMETADATA_LOCATION_TOO_LONG)); - assert!(string::length(&utf8(metadata_hash)) <= 256, error::invalid_argument(EMETADATA_HASH_TOO_LONG)); + assert!( + string::length(&utf8(metadata_location)) <= 256, + error::invalid_argument(EMETADATA_LOCATION_TOO_LONG) + ); + assert!( + string::length(&utf8(metadata_hash)) <= 256, + error::invalid_argument(EMETADATA_HASH_TOO_LONG) + ); let metadata = simple_map::create>(); simple_map::add(&mut metadata, utf8(METADATA_LOCATION_KEY), metadata_location); @@ -526,8 +585,7 @@ module supra_framework::supra_governance { #[test_only] public entry fun supra_create_proposal_for_test( - proposer: &signer, - multi_step: bool, + proposer: &signer, multi_step: bool ) acquires SupraGovernanceConfig, SupraGovernanceEvents { let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); @@ -537,14 +595,14 @@ module supra_framework::supra_governance { execution_hash, b"", b"", - true, + true ); } else { supra_create_proposal( proposer, execution_hash, b"", - b"", + b"" ); }; } @@ -561,9 +619,13 @@ module supra_framework::supra_governance { vector::push_back(&mut execution_hash, 1); if (finish_multi_step_execution) { - resolve_supra_multi_step_proposal(proposal_id, signer_address, vector::empty()) + resolve_supra_multi_step_proposal( + proposal_id, signer_address, vector::empty() + ) } else { - resolve_supra_multi_step_proposal(proposal_id, signer_address, execution_hash) + resolve_supra_multi_step_proposal( + proposal_id, signer_address, execution_hash + ) } } else { supra_resolve(proposal_id, signer_address) @@ -572,7 +634,9 @@ module supra_framework::supra_governance { #[test_only] /// Force reconfigure. To be called at the end of a proposal that alters on-chain configs. - public fun toggle_features_for_test(enable: vector, disable: vector) { + public fun toggle_features_for_test( + enable: vector, disable: vector + ) { toggle_features(&account::create_signer_for_test(@0x1), enable, disable); } @@ -583,9 +647,13 @@ module supra_framework::supra_governance { yes_voter: &signer, no_voter: &signer, multi_step: bool, - use_generic_resolve_function: bool, + use_generic_resolve_function: bool ) acquires ApprovedExecutionHashes, SupraGovernanceConfig, GovernanceResponsbility, SupraGovernanceEvents { - let voters = vector[signer::address_of(proposer), signer::address_of(yes_voter), signer::address_of(no_voter)]; + let voters = vector[ + signer::address_of(proposer), + signer::address_of(yes_voter), + signer::address_of(no_voter) + ]; supra_setup_voting(supra_framework, voters); let execution_hash = vector::empty(); @@ -597,71 +665,109 @@ module supra_framework::supra_governance { supra_vote(yes_voter, 0, true); supra_vote(no_voter, 0, false); - supra_test_resolving_proposal_generic(supra_framework, use_generic_resolve_function, execution_hash); + supra_test_resolving_proposal_generic( + supra_framework, use_generic_resolve_function, execution_hash + ); } #[test_only] public entry fun supra_test_resolving_proposal_generic( supra_framework: &signer, use_generic_resolve_function: bool, - execution_hash: vector, + execution_hash: vector ) acquires ApprovedExecutionHashes, GovernanceResponsbility { // Once expiration time has passed, the proposal should be considered resolve now as there are more yes votes // than no. timestamp::update_global_time_for_test(100001000000); - let proposal_state = multisig_voting::get_proposal_state(signer::address_of(supra_framework), 0); + let proposal_state = + multisig_voting::get_proposal_state( + signer::address_of(supra_framework), 0 + ); assert!(proposal_state == PROPOSAL_STATE_SUCCEEDED, proposal_state); // Add approved script hash. add_supra_approved_script_hash(0); - let approved_hashes = borrow_global(@supra_framework).hashes; + let approved_hashes = + borrow_global(@supra_framework).hashes; assert!(*simple_map::borrow(&approved_hashes, &0) == execution_hash, 0); // Resolve the proposal. - let account = supra_resolve_proposal_for_test(0, @supra_framework, use_generic_resolve_function, true); + let account = + supra_resolve_proposal_for_test( + 0, @supra_framework, use_generic_resolve_function, true + ); assert!(signer::address_of(&account) == @supra_framework, 1); assert!(multisig_voting::is_resolved(@supra_framework, 0), 2); - let approved_hashes = borrow_global(@supra_framework).hashes; + let approved_hashes = + borrow_global(@supra_framework).hashes; assert!(!simple_map::contains_key(&approved_hashes, &0), 3); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_voting( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, SupraGovernanceConfig, GovernanceResponsbility, SupraGovernanceEvents { test_voting_generic(supra_framework, proposer, yes_voter, no_voter, false, false); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_voting_multi_step( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, SupraGovernanceConfig, GovernanceResponsbility, SupraGovernanceEvents { test_voting_generic(supra_framework, proposer, yes_voter, no_voter, true, true); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] #[expected_failure(abort_code = 0x5000a, location = supra_framework::multisig_voting)] public entry fun test_voting_multi_step_cannot_use_single_step_resolve( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, SupraGovernanceConfig, GovernanceResponsbility, SupraGovernanceEvents { test_voting_generic(supra_framework, proposer, yes_voter, no_voter, true, false); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_voting_single_step_can_use_generic_resolve_function( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, SupraGovernanceConfig, GovernanceResponsbility, SupraGovernanceEvents { test_voting_generic(supra_framework, proposer, yes_voter, no_voter, false, true); } @@ -672,9 +778,13 @@ module supra_framework::supra_governance { proposer: &signer, yes_voter: &signer, no_voter: &signer, - multi_step: bool, + multi_step: bool ) acquires ApprovedExecutionHashes, GovernanceResponsbility, SupraGovernanceEvents, SupraGovernanceConfig { - let voters = vector[signer::address_of(proposer), signer::address_of(yes_voter), signer::address_of(no_voter)]; + let voters = vector[ + signer::address_of(proposer), + signer::address_of(yes_voter), + signer::address_of(no_voter) + ]; supra_setup_voting(supra_framework, voters); supra_create_proposal_for_test(proposer, multi_step); @@ -691,8 +801,12 @@ module supra_framework::supra_governance { let execution_hash = vector::empty(); let next_execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); - multisig_voting::resolve_proposal_v2(@supra_framework, 0, next_execution_hash); - assert!(multisig_voting::is_resolved(@supra_framework, 0), 0); + multisig_voting::resolve_proposal_v2( + @supra_framework, 0, next_execution_hash + ); + assert!( + multisig_voting::is_resolved(@supra_framework, 0), 0 + ); if (vector::length(&next_execution_hash) == 0) { remove_supra_approved_hash(0); } else { @@ -700,19 +814,29 @@ module supra_framework::supra_governance { }; } else { multisig_voting::resolve(@supra_framework, 0); - assert!(multisig_voting::is_resolved(@supra_framework, 0), 0); + assert!( + multisig_voting::is_resolved(@supra_framework, 0), 0 + ); remove_supra_approved_hash(0); }; - let approved_hashes = borrow_global(@supra_framework).hashes; + let approved_hashes = + borrow_global(@supra_framework).hashes; assert!(!simple_map::contains_key(&approved_hashes, &0), 1); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_can_remove_approved_hash_if_executed_directly_via_voting( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, GovernanceResponsbility, SupraGovernanceEvents, SupraGovernanceConfig { test_can_remove_approved_hash_if_executed_directly_via_voting_generic( supra_framework, @@ -723,12 +847,19 @@ module supra_framework::supra_governance { ); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_can_remove_approved_hash_if_executed_directly_via_voting_multi_step( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires ApprovedExecutionHashes, GovernanceResponsbility, SupraGovernanceEvents, SupraGovernanceConfig { test_can_remove_approved_hash_if_executed_directly_via_voting_generic( supra_framework, @@ -739,22 +870,33 @@ module supra_framework::supra_governance { ); } - #[test(supra_framework = @supra_framework, proposer = @0x123, voter_1 = @0x234, voter_2 = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + voter_1 = @0x234, + voter_2 = @345 + ) + ] #[expected_failure(abort_code = 0x8000d, location = supra_framework::multisig_voting)] public entry fun test_cannot_double_vote( supra_framework: &signer, proposer: &signer, voter_1: &signer, - voter_2: &signer, + voter_2: &signer ) acquires ApprovedExecutionHashes, GovernanceResponsbility, SupraGovernanceConfig, SupraGovernanceEvents { - let voters = vector[signer::address_of(proposer), signer::address_of(voter_1), signer::address_of(voter_2)]; + let voters = vector[ + signer::address_of(proposer), + signer::address_of(voter_1), + signer::address_of(voter_2) + ]; supra_setup_voting(supra_framework, voters); supra_create_proposal( proposer, b"random-test", b"", - b"", + b"" ); // Double voting should throw an error. @@ -764,8 +906,7 @@ module supra_framework::supra_governance { #[test_only] public fun supra_setup_voting( - supra_framework: &signer, - voters: vector
, + supra_framework: &signer, voters: vector
) acquires GovernanceResponsbility { use supra_framework::account; @@ -777,13 +918,13 @@ module supra_framework::supra_governance { store_signer_cap( supra_framework, @supra_framework, - account::create_test_signer_cap(@supra_framework), + account::create_test_signer_cap(@supra_framework) ); } #[test(supra_framework = @supra_framework)] public entry fun test_update_governance_config( - supra_framework: signer, + supra_framework: signer ) acquires SupraGovernanceEvents, SupraGovernanceConfig { account::create_account_for_test(signer::address_of(&supra_framework)); let voters = vector[@0xa1, @0xa2, @0xa3]; @@ -799,8 +940,9 @@ module supra_framework::supra_governance { #[test(account = @0x123)] #[expected_failure(abort_code = 0x50003, location = supra_framework::system_addresses)] - public entry fun test_update_governance_config_unauthorized_should_fail(account: signer) - acquires SupraGovernanceConfig, SupraGovernanceEvents { + public entry fun test_update_governance_config_unauthorized_should_fail( + account: signer + ) acquires SupraGovernanceConfig, SupraGovernanceEvents { account::create_account_for_test(signer::address_of(&account)); let voters = vector[@0xa1, @0xa2, @0xa3]; @@ -808,14 +950,25 @@ module supra_framework::supra_governance { update_supra_governance_config(&account, 1500, 2, voters); } - #[test(supra_framework = @supra_framework, proposer = @0x123, yes_voter = @0x234, no_voter = @345)] + #[ + test( + supra_framework = @supra_framework, + proposer = @0x123, + yes_voter = @0x234, + no_voter = @345 + ) + ] public entry fun test_replace_execution_hash( supra_framework: &signer, proposer: &signer, yes_voter: &signer, - no_voter: &signer, + no_voter: &signer ) acquires GovernanceResponsbility, ApprovedExecutionHashes, SupraGovernanceConfig, SupraGovernanceEvents { - let voters = vector[signer::address_of(proposer), signer::address_of(yes_voter), signer::address_of(no_voter)]; + let voters = vector[ + signer::address_of(proposer), + signer::address_of(yes_voter), + signer::address_of(no_voter) + ]; supra_setup_voting(supra_framework, voters); supra_create_proposal_for_test(proposer, true); @@ -833,7 +986,9 @@ module supra_framework::supra_governance { vector::push_back(&mut execution_hash, 1); vector::push_back(&mut next_execution_hash, 10); - multisig_voting::resolve_proposal_v2(@supra_framework, 0, next_execution_hash); + multisig_voting::resolve_proposal_v2( + @supra_framework, 0, next_execution_hash + ); if (vector::length(&next_execution_hash) == 0) { remove_supra_approved_hash(0); @@ -841,8 +996,9 @@ module supra_framework::supra_governance { add_supra_approved_script_hash(0) }; - let approved_hashes = borrow_global(@supra_framework).hashes; - assert!(*simple_map::borrow(&approved_hashes, &0) == vector[10u8, ], 1); + let approved_hashes = + borrow_global(@supra_framework).hashes; + assert!(*simple_map::borrow(&approved_hashes, &0) == vector[10u8], 1); } #[verify_only] @@ -850,8 +1006,13 @@ module supra_framework::supra_governance { supra_framework: &signer, voting_duration_secs: u64, supra_min_voting_threshold: u64, - voters: vector
, + voters: vector
) { - initialize(supra_framework, voting_duration_secs, supra_min_voting_threshold, voters); + initialize( + supra_framework, + voting_duration_secs, + supra_min_voting_threshold, + voters + ); } } diff --git a/aptos-move/framework/supra-framework/sources/system_addresses.move b/aptos-move/framework/supra-framework/sources/system_addresses.move index 677025c613b63..718dafdea1716 100644 --- a/aptos-move/framework/supra-framework/sources/system_addresses.move +++ b/aptos-move/framework/supra-framework/sources/system_addresses.move @@ -16,7 +16,10 @@ module supra_framework::system_addresses { } public fun assert_core_resource_address(addr: address) { - assert!(is_core_resource_address(addr), error::permission_denied(ENOT_CORE_RESOURCE_ADDRESS)) + assert!( + is_core_resource_address(addr), + error::permission_denied(ENOT_CORE_RESOURCE_ADDRESS) + ) } public fun is_core_resource_address(addr: address): bool { @@ -26,7 +29,7 @@ module supra_framework::system_addresses { public fun assert_supra_framework(account: &signer) { assert!( is_supra_framework_address(signer::address_of(account)), - error::permission_denied(ENOT_APTOS_FRAMEWORK_ADDRESS), + error::permission_denied(ENOT_APTOS_FRAMEWORK_ADDRESS) ) } @@ -37,22 +40,22 @@ module supra_framework::system_addresses { public fun assert_framework_reserved(addr: address) { assert!( is_framework_reserved_address(addr), - error::permission_denied(ENOT_FRAMEWORK_RESERVED_ADDRESS), + error::permission_denied(ENOT_FRAMEWORK_RESERVED_ADDRESS) ) } /// Return true if `addr` is 0x0 or under the on chain governance's control. public fun is_framework_reserved_address(addr: address): bool { - is_supra_framework_address(addr) || - addr == @0x2 || - addr == @0x3 || - addr == @0x4 || - addr == @0x5 || - addr == @0x6 || - addr == @0x7 || - addr == @0x8 || - addr == @0x9 || - addr == @0xa + is_supra_framework_address(addr) + || addr == @0x2 + || addr == @0x3 + || addr == @0x4 + || addr == @0x5 + || addr == @0x6 + || addr == @0x7 + || addr == @0x8 + || addr == @0x9 + || addr == @0xa } /// Return true if `addr` is 0x1. diff --git a/aptos-move/framework/supra-framework/sources/system_addresses.spec.move b/aptos-move/framework/supra-framework/sources/system_addresses.spec.move index f6c64ce9ed406..ee2dd80466d19 100644 --- a/aptos-move/framework/supra-framework/sources/system_addresses.spec.move +++ b/aptos-move/framework/supra-framework/sources/system_addresses.spec.move @@ -64,6 +64,7 @@ spec supra_framework::system_addresses { spec assert_framework_reserved(addr: address) { aborts_if !is_framework_reserved_address(addr); } + /// Specifies that a function aborts if the account does not have the aptos framework address. spec schema AbortsIfNotAptosFramework { account: signer; diff --git a/aptos-move/framework/supra-framework/sources/timestamp.move b/aptos-move/framework/supra-framework/sources/timestamp.move index 4c9f25bd06c82..9d16e9bb66187 100644 --- a/aptos-move/framework/supra-framework/sources/timestamp.move +++ b/aptos-move/framework/supra-framework/sources/timestamp.move @@ -10,7 +10,7 @@ module supra_framework::timestamp { /// A singleton resource holding the current Unix time in microseconds struct CurrentTimeMicroseconds has key { - microseconds: u64, + microseconds: u64 } /// Conversion factor between seconds and microseconds @@ -22,7 +22,9 @@ module supra_framework::timestamp { const EINVALID_TIMESTAMP: u64 = 2; /// Marks that time has started. This can only be called from genesis and with the aptos framework account. - public(friend) fun set_time_has_started(supra_framework: &signer, start_time_in_microseconds: u64) { + public(friend) fun set_time_has_started( + supra_framework: &signer, start_time_in_microseconds: u64 + ) { system_addresses::assert_supra_framework(supra_framework); let timer = CurrentTimeMicroseconds { microseconds: start_time_in_microseconds }; move_to(supra_framework, timer); @@ -30,9 +32,7 @@ module supra_framework::timestamp { /// Updates the wall clock time by consensus. Requires VM privilege and will be invoked during block prologue. public fun update_global_time( - account: &signer, - proposer: address, - timestamp: u64 + account: &signer, proposer: address, timestamp: u64 ) acquires CurrentTimeMicroseconds { // Can only be invoked by AptosVM signer. system_addresses::assert_vm(account); @@ -52,7 +52,7 @@ module supra_framework::timestamp { #[test_only] public fun set_time_has_started_for_testing(account: &signer) { if (!exists(@supra_framework)) { - set_time_has_started(account,0); + set_time_has_started(account, 0); }; } @@ -69,7 +69,9 @@ module supra_framework::timestamp { } #[test_only] - public fun update_global_time_for_test(timestamp_microsecs: u64) acquires CurrentTimeMicroseconds { + public fun update_global_time_for_test( + timestamp_microsecs: u64 + ) acquires CurrentTimeMicroseconds { let global_timer = borrow_global_mut(@supra_framework); let now = global_timer.microseconds; assert!(now < timestamp_microsecs, error::invalid_argument(EINVALID_TIMESTAMP)); @@ -77,7 +79,9 @@ module supra_framework::timestamp { } #[test_only] - public fun update_global_time_for_test_secs(timestamp_seconds: u64) acquires CurrentTimeMicroseconds { + public fun update_global_time_for_test_secs( + timestamp_seconds: u64 + ) acquires CurrentTimeMicroseconds { update_global_time_for_test(timestamp_seconds * MICRO_CONVERSION_FACTOR); } diff --git a/aptos-move/framework/supra-framework/sources/timestamp.spec.move b/aptos-move/framework/supra-framework/sources/timestamp.spec.move index d6cecff444b2b..57a54cf74ceed 100644 --- a/aptos-move/framework/supra-framework/sources/timestamp.spec.move +++ b/aptos-move/framework/supra-framework/sources/timestamp.spec.move @@ -33,14 +33,16 @@ spec supra_framework::timestamp { use supra_framework::chain_status; /// [high-level-req-1] /// [high-level-req-2] - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework); } spec update_global_time { use supra_framework::chain_status; requires chain_status::is_operating(); include UpdateGlobalTimeAbortsIf; - ensures (proposer != @vm_reserved) ==> (spec_now_microseconds() == timestamp); + ensures (proposer != @vm_reserved) ==> + (spec_now_microseconds() == timestamp); } spec schema UpdateGlobalTimeAbortsIf { diff --git a/aptos-move/framework/supra-framework/sources/transaction_context.move b/aptos-move/framework/supra-framework/sources/transaction_context.move index 0b4c163107f36..6f7591667b5c8 100644 --- a/aptos-move/framework/supra-framework/sources/transaction_context.move +++ b/aptos-move/framework/supra-framework/sources/transaction_context.move @@ -22,13 +22,13 @@ module supra_framework::transaction_context { module_name: String, function_name: String, ty_args_names: vector, - args: vector>, + args: vector> } /// Represents the multisig payload. struct MultisigPayload has copy, drop { multisig_address: address, - entry_function_payload: Option, + entry_function_payload: Option } /// Returns the transaction hash of the current transaction. @@ -63,9 +63,7 @@ module supra_framework::transaction_context { /// This method runs `generate_unique_address` native function and returns /// the generated unique address wrapped in the AUID class. public fun generate_auid(): AUID { - return AUID { - unique_address: generate_unique_address() - } + return AUID { unique_address: generate_unique_address() } } /// Returns the unique address wrapped in the given AUID struct. @@ -76,18 +74,26 @@ module supra_framework::transaction_context { /// Returns the sender's address for the current transaction. /// This function aborts if called outside of the transaction prologue, execution, or epilogue phases. public fun sender(): address { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); sender_internal() } + native fun sender_internal(): address; /// Returns the list of the secondary signers for the current transaction. /// If the current transaction has no secondary signers, this function returns an empty vector. /// This function aborts if called outside of the transaction prologue, execution, or epilogue phases. public fun secondary_signers(): vector
{ - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); secondary_signers_internal() } + native fun secondary_signers_internal(): vector
; /// Returns the gas payer address for the current transaction. @@ -95,90 +101,137 @@ module supra_framework::transaction_context { /// or the address of the separate gas fee payer if one is specified. /// This function aborts if called outside of the transaction prologue, execution, or epilogue phases. public fun gas_payer(): address { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); gas_payer_internal() } + native fun gas_payer_internal(): address; /// Returns the max gas amount in units which is specified for the current transaction. /// This function aborts if called outside of the transaction prologue, execution, or epilogue phases. public fun max_gas_amount(): u64 { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); max_gas_amount_internal() } + native fun max_gas_amount_internal(): u64; /// Returns the gas unit price in Quants which is specified for the current transaction. /// This function aborts if called outside of the transaction prologue, execution, or epilogue phases. public fun gas_unit_price(): u64 { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); gas_unit_price_internal() } + native fun gas_unit_price_internal(): u64; /// Returns the chain ID specified for the current transaction. /// This function aborts if called outside of the transaction prologue, execution, or epilogue phases. public fun chain_id(): u8 { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); chain_id_internal() } + native fun chain_id_internal(): u8; /// Returns the entry function payload if the current transaction has such a payload. Otherwise, return `None`. /// This function aborts if called outside of the transaction prologue, execution, or epilogue phases. public fun entry_function_payload(): Option { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); entry_function_payload_internal() } + native fun entry_function_payload_internal(): Option; /// Returns the account address of the entry function payload. public fun account_address(payload: &EntryFunctionPayload): address { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); payload.account_address } /// Returns the module name of the entry function payload. public fun module_name(payload: &EntryFunctionPayload): String { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); payload.module_name } /// Returns the function name of the entry function payload. public fun function_name(payload: &EntryFunctionPayload): String { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); payload.function_name } /// Returns the type arguments names of the entry function payload. public fun type_arg_names(payload: &EntryFunctionPayload): vector { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); payload.ty_args_names } /// Returns the arguments of the entry function payload. public fun args(payload: &EntryFunctionPayload): vector> { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); payload.args } /// Returns the multisig payload if the current transaction has such a payload. Otherwise, return `None`. /// This function aborts if called outside of the transaction prologue, execution, or epilogue phases. public fun multisig_payload(): Option { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); multisig_payload_internal() } + native fun multisig_payload_internal(): Option; /// Returns the multisig account address of the multisig payload. public fun multisig_address(payload: &MultisigPayload): address { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); payload.multisig_address } /// Returns the inner entry function payload of the multisig payload. - public fun inner_entry_function_payload(payload: &MultisigPayload): Option { - assert!(features::transaction_context_extension_enabled(), error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED)); + public fun inner_entry_function_payload( + payload: &MultisigPayload + ): Option { + assert!( + features::transaction_context_extension_enabled(), + error::invalid_state(ETRANSACTION_CONTEXT_EXTENSION_NOT_ENABLED) + ); payload.entry_function_payload } @@ -205,56 +258,56 @@ module supra_framework::transaction_context { } #[test] - #[expected_failure(abort_code=196609, location = Self)] + #[expected_failure(abort_code = 196609, location = Self)] fun test_call_sender() { // expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)` let _sender = sender(); } #[test] - #[expected_failure(abort_code=196609, location = Self)] + #[expected_failure(abort_code = 196609, location = Self)] fun test_call_secondary_signers() { // expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)` let _secondary_signers = secondary_signers(); } #[test] - #[expected_failure(abort_code=196609, location = Self)] + #[expected_failure(abort_code = 196609, location = Self)] fun test_call_gas_payer() { // expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)` let _gas_payer = gas_payer(); } #[test] - #[expected_failure(abort_code=196609, location = Self)] + #[expected_failure(abort_code = 196609, location = Self)] fun test_call_max_gas_amount() { // expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)` let _max_gas_amount = max_gas_amount(); } #[test] - #[expected_failure(abort_code=196609, location = Self)] + #[expected_failure(abort_code = 196609, location = Self)] fun test_call_gas_unit_price() { // expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)` let _gas_unit_price = gas_unit_price(); } #[test] - #[expected_failure(abort_code=196609, location = Self)] + #[expected_failure(abort_code = 196609, location = Self)] fun test_call_chain_id() { // expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)` let _chain_id = chain_id(); } #[test] - #[expected_failure(abort_code=196609, location = Self)] + #[expected_failure(abort_code = 196609, location = Self)] fun test_call_entry_function_payload() { // expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)` let _entry_fun = entry_function_payload(); } #[test] - #[expected_failure(abort_code=196609, location = Self)] + #[expected_failure(abort_code = 196609, location = Self)] fun test_call_multisig_payload() { // expected to fail with the error code of `invalid_state(E_TRANSACTION_CONTEXT_NOT_AVAILABLE)` let _multisig = multisig_payload(); diff --git a/aptos-move/framework/supra-framework/sources/transaction_context.spec.move b/aptos-move/framework/supra-framework/sources/transaction_context.spec.move index 25fd21a3a520a..d55dbc7f02027 100644 --- a/aptos-move/framework/supra-framework/sources/transaction_context.spec.move +++ b/aptos-move/framework/supra-framework/sources/transaction_context.spec.move @@ -41,13 +41,17 @@ spec supra_framework::transaction_context { ensures [abstract] result == spec_get_script_hash(); ensures [abstract] len(result) == 32; } + spec fun spec_get_script_hash(): vector; + spec get_txn_hash(): vector { pragma opaque; aborts_if [abstract] false; ensures result == spec_get_txn_hash(); } + spec fun spec_get_txn_hash(): vector; + spec get_transaction_hash(): vector { pragma opaque; aborts_if [abstract] false; @@ -56,17 +60,21 @@ spec supra_framework::transaction_context { /// [high-level-req-1] ensures [abstract] len(result) == 32; } + spec generate_unique_address(): address { pragma opaque; ensures [abstract] result == spec_generate_unique_address(); } + spec fun spec_generate_unique_address(): address; + spec generate_auid_address(): address { pragma opaque; // property 3: Generating the unique address should return a vector with 32 bytes, if the auid feature flag is enabled. /// [high-level-req-3] ensures [abstract] result == spec_generate_unique_address(); } + spec auid_address(auid: &AUID): address { // property 2: Fetching the unique address should never abort. /// [high-level-req-2] @@ -77,26 +85,32 @@ spec supra_framework::transaction_context { //TODO: temporary mockup pragma opaque; } + spec secondary_signers_internal(): vector
{ //TODO: temporary mockup pragma opaque; } + spec gas_payer_internal(): address { //TODO: temporary mockup pragma opaque; } + spec max_gas_amount_internal(): u64 { //TODO: temporary mockup pragma opaque; } + spec gas_unit_price_internal(): u64 { //TODO: temporary mockup pragma opaque; } + spec chain_id_internal(): u8 { //TODO: temporary mockup pragma opaque; } + spec entry_function_payload_internal(): Option { //TODO: temporary mockup pragma opaque; diff --git a/aptos-move/framework/supra-framework/sources/transaction_fee.move b/aptos-move/framework/supra-framework/sources/transaction_fee.move index d0f96d2ae2841..8447a612f2191 100644 --- a/aptos-move/framework/supra-framework/sources/transaction_fee.move +++ b/aptos-move/framework/supra-framework/sources/transaction_fee.move @@ -1,6 +1,12 @@ /// This module provides an interface to burn or collect and redistribute transaction fees. module supra_framework::transaction_fee { - use supra_framework::coin::{Self, AggregatableCoin, BurnCapability, Coin, MintCapability}; + use supra_framework::coin::{ + Self, + AggregatableCoin, + BurnCapability, + Coin, + MintCapability + }; use supra_framework::supra_account; use supra_framework::supra_coin::SupraCoin; use supra_framework::stake; @@ -31,17 +37,17 @@ module supra_framework::transaction_fee { /// Stores burn capability to burn the gas fees. struct SupraCoinCapabilities has key { - burn_cap: BurnCapability, + burn_cap: BurnCapability } /// Stores burn capability to burn the gas fees. struct SupraFABurnCapabilities has key { - burn_ref: BurnRef, + burn_ref: BurnRef } /// Stores mint capability to mint the refunds. struct SupraCoinMintCapability has key { - mint_cap: MintCapability, + mint_cap: MintCapability } /// Stores information about the block proposer and the amount of fees @@ -49,7 +55,7 @@ module supra_framework::transaction_fee { struct CollectedFeesPerBlock has key { amount: AggregatableCoin, proposer: Option
, - burn_percentage: u8, + burn_percentage: u8 } #[event] @@ -82,12 +88,14 @@ module supra_framework::transaction_fee { /// Storage fee charge. storage_fee_quants: u64, /// Storage fee refund. - storage_fee_refund_quants: u64, + storage_fee_refund_quants: u64 } /// Initializes the resource storing information about gas fees collection and /// distribution. Should be called by on-chain governance. - public fun initialize_fee_collection_and_distribution(supra_framework: &signer, burn_percentage: u8) { + public fun initialize_fee_collection_and_distribution( + supra_framework: &signer, burn_percentage: u8 + ) { system_addresses::assert_supra_framework(supra_framework); assert!( !exists(@supra_framework), @@ -102,7 +110,7 @@ module supra_framework::transaction_fee { let collected_fees = CollectedFeesPerBlock { amount: coin::initialize_aggregatable_coin(supra_framework), proposer: option::none(), - burn_percentage, + burn_percentage }; move_to(supra_framework, collected_fees); } @@ -113,8 +121,7 @@ module supra_framework::transaction_fee { /// Sets the burn percentage for collected fees to a new value. Should be called by on-chain governance. public fun upgrade_burn_percentage( - supra_framework: &signer, - new_burn_percentage: u8 + supra_framework: &signer, new_burn_percentage: u8 ) acquires SupraCoinCapabilities, CollectedFeesPerBlock { system_addresses::assert_supra_framework(supra_framework); assert!(new_burn_percentage <= 100, error::out_of_range(EINVALID_BURN_PERCENTAGE)); @@ -126,22 +133,28 @@ module supra_framework::transaction_fee { if (is_fees_collection_enabled()) { // Upgrade has no effect unless fees are being collected. - let burn_percentage = &mut borrow_global_mut(@supra_framework).burn_percentage; + let burn_percentage = + &mut borrow_global_mut(@supra_framework).burn_percentage; *burn_percentage = new_burn_percentage } } /// Registers the proposer of the block for gas fees collection. This function /// can only be called at the beginning of the block. - public(friend) fun register_proposer_for_fee_collection(proposer_addr: address) acquires CollectedFeesPerBlock { + public(friend) fun register_proposer_for_fee_collection( + proposer_addr: address + ) acquires CollectedFeesPerBlock { if (is_fees_collection_enabled()) { - let collected_fees = borrow_global_mut(@supra_framework); + let collected_fees = + borrow_global_mut(@supra_framework); let _ = option::swap_or_fill(&mut collected_fees.proposer, proposer_addr); } } /// Burns a specified fraction of the coin. - fun burn_coin_fraction(coin: &mut Coin, burn_percentage: u8) acquires SupraCoinCapabilities { + fun burn_coin_fraction( + coin: &mut Coin, burn_percentage: u8 + ) acquires SupraCoinCapabilities { assert!(burn_percentage <= 100, error::out_of_range(EINVALID_BURN_PERCENTAGE)); let collected_amount = coin::value(coin); @@ -154,7 +167,7 @@ module supra_framework::transaction_fee { let coin_to_burn = coin::extract(coin, amount_to_burn); coin::burn( coin_to_burn, - &borrow_global(@supra_framework).burn_cap, + &borrow_global(@supra_framework).burn_cap ); } } @@ -163,9 +176,7 @@ module supra_framework::transaction_fee { /// end of an epoch, and records it in the system. This function can only be called /// at the beginning of the block or during reconfiguration. public(friend) fun process_collected_fees() acquires SupraCoinCapabilities, CollectedFeesPerBlock { - if (!is_fees_collection_enabled()) { - return - }; + if (!is_fees_collection_enabled()) { return }; let collected_fees = borrow_global_mut(@supra_framework); // If there are no collected fees, only unset the proposer. See the rationale for @@ -208,12 +219,16 @@ module supra_framework::transaction_fee { } /// Burn transaction fees in epilogue. - public(friend) fun burn_fee(account: address, fee: u64) acquires SupraFABurnCapabilities, SupraCoinCapabilities { + public(friend) fun burn_fee( + account: address, fee: u64 + ) acquires SupraFABurnCapabilities, SupraCoinCapabilities { if (exists(@supra_framework)) { - let burn_ref = &borrow_global(@supra_framework).burn_ref; + let burn_ref = + &borrow_global(@supra_framework).burn_ref; supra_account::burn_from_fungible_store(burn_ref, account, fee); } else { - let burn_cap = &borrow_global(@supra_framework).burn_cap; + let burn_cap = + &borrow_global(@supra_framework).burn_cap; if (features::operations_default_to_fa_supra_store_enabled()) { let (burn_ref, burn_receipt) = coin::get_paired_burn_ref(burn_cap); supra_account::burn_from_fungible_store(&burn_ref, account, fee); @@ -222,14 +237,16 @@ module supra_framework::transaction_fee { coin::burn_from( account, fee, - burn_cap, + burn_cap ); }; }; } /// Mint refund in epilogue. - public(friend) fun mint_and_refund(account: address, refund: u64) acquires SupraCoinMintCapability { + public(friend) fun mint_and_refund( + account: address, refund: u64 + ) acquires SupraCoinMintCapability { let mint_cap = &borrow_global(@supra_framework).mint_cap; let refund_coin = coin::mint(refund, mint_cap); coin::force_deposit(account, refund_coin); @@ -247,7 +264,9 @@ module supra_framework::transaction_fee { } /// Only called during genesis. - public(friend) fun store_supra_coin_burn_cap(supra_framework: &signer, burn_cap: BurnCapability) { + public(friend) fun store_supra_coin_burn_cap( + supra_framework: &signer, burn_cap: BurnCapability + ) { system_addresses::assert_supra_framework(supra_framework); if (features::operations_default_to_fa_supra_store_enabled()) { @@ -258,18 +277,24 @@ module supra_framework::transaction_fee { } } - public entry fun convert_to_aptos_fa_burn_ref(supra_framework: &signer) acquires SupraCoinCapabilities { - assert!(features::operations_default_to_fa_supra_store_enabled(), EFA_GAS_CHARGING_NOT_ENABLED); + public entry fun convert_to_aptos_fa_burn_ref( + supra_framework: &signer + ) acquires SupraCoinCapabilities { + assert!( + features::operations_default_to_fa_supra_store_enabled(), + EFA_GAS_CHARGING_NOT_ENABLED + ); system_addresses::assert_supra_framework(supra_framework); - let SupraCoinCapabilities { - burn_cap, - } = move_from(signer::address_of(supra_framework)); + let SupraCoinCapabilities { burn_cap } = + move_from(signer::address_of(supra_framework)); let burn_ref = coin::convert_and_take_paired_burn_ref(burn_cap); move_to(supra_framework, SupraFABurnCapabilities { burn_ref }); } /// Only called during genesis. - public(friend) fun store_supra_coin_mint_cap(supra_framework: &signer, mint_cap: MintCapability) { + public(friend) fun store_supra_coin_mint_cap( + supra_framework: &signer, mint_cap: MintCapability + ) { system_addresses::assert_supra_framework(supra_framework); move_to(supra_framework, SupraCoinMintCapability { mint_cap }) } @@ -290,7 +315,9 @@ module supra_framework::transaction_fee { use supra_framework::object; #[test(supra_framework = @supra_framework)] - fun test_initialize_fee_collection_and_distribution(supra_framework: signer) acquires CollectedFeesPerBlock { + fun test_initialize_fee_collection_and_distribution( + supra_framework: signer + ) acquires CollectedFeesPerBlock { aggregator_factory::initialize_aggregator_factory_for_test(&supra_framework); initialize_fee_collection_and_distribution(&supra_framework, 25); @@ -342,12 +369,19 @@ module supra_framework::transaction_fee { coin::destroy_mint_cap(mint_cap); } - #[test(supra_framework = @supra_framework, alice = @0xa11ce, bob = @0xb0b, carol = @0xca101)] + #[ + test( + supra_framework = @supra_framework, + alice = @0xa11ce, + bob = @0xb0b, + carol = @0xca101 + ) + ] fun test_fees_distribution( supra_framework: signer, alice: signer, bob: signer, - carol: signer, + carol: signer ) acquires SupraCoinCapabilities, CollectedFeesPerBlock { use std::signer; use supra_framework::supra_account; @@ -365,7 +399,11 @@ module supra_framework::transaction_fee { supra_account::create_account(alice_addr); supra_account::create_account(bob_addr); supra_account::create_account(carol_addr); - assert!(object::object_address(&coin::ensure_paired_metadata()) == @aptos_fungible_asset, 0); + assert!( + object::object_address(&coin::ensure_paired_metadata()) + == @aptos_fungible_asset, + 0 + ); coin::deposit(alice_addr, coin::mint(10000, &mint_cap)); coin::deposit(bob_addr, coin::mint(10000, &mint_cap)); coin::deposit(carol_addr, coin::mint(10000, &mint_cap)); diff --git a/aptos-move/framework/supra-framework/sources/transaction_fee.spec.move b/aptos-move/framework/supra-framework/sources/transaction_fee.spec.move index 0464966ff45f0..0db4a0d86496f 100644 --- a/aptos-move/framework/supra-framework/sources/transaction_fee.spec.move +++ b/aptos-move/framework/supra-framework/sources/transaction_fee.spec.move @@ -58,7 +58,9 @@ spec supra_framework::transaction_fee { pragma aborts_if_is_strict; // property 1: Given the blockchain is in an operating state, it guarantees that the Supra framework signer may burn Supra coins. /// [high-level-req-1] - invariant [suspendable] chain_status::is_operating() ==> exists(@supra_framework) || exists(@supra_framework); + invariant [suspendable] chain_status::is_operating() ==> + exists(@supra_framework) + || exists(@supra_framework); } spec CollectedFeesPerBlock { @@ -67,7 +69,9 @@ spec supra_framework::transaction_fee { invariant burn_percentage <= 100; } - spec initialize_fee_collection_and_distribution(supra_framework: &signer, burn_percentage: u8) { + spec initialize_fee_collection_and_distribution( + supra_framework: &signer, burn_percentage: u8 + ) { use std::signer; use supra_framework::stake::ValidatorFees; use supra_framework::aggregator_factory; @@ -110,7 +114,8 @@ spec supra_framework::transaction_fee { // The effect of upgrading the burn percentage ensures exists(@supra_framework) ==> - global(@supra_framework).burn_percentage == new_burn_percentage; + global(@supra_framework).burn_percentage + == new_burn_percentage; } spec register_proposer_for_fee_collection(proposer_addr: address) { @@ -118,7 +123,8 @@ spec supra_framework::transaction_fee { // property 6: Ensure the presence of the resource. /// [high-level-req-6.1] ensures is_fees_collection_enabled() ==> - option::spec_borrow(global(@supra_framework).proposer) == proposer_addr; + option::spec_borrow(global(@supra_framework).proposer) == + proposer_addr; } spec burn_coin_fraction(coin: &mut Coin, burn_percentage: u8) { @@ -131,7 +137,8 @@ spec supra_framework::transaction_fee { let amount_to_burn = (burn_percentage * coin::value(coin)) / 100; // include (amount_to_burn > 0) ==> coin::AbortsIfNotExistCoinInfo; - include amount_to_burn > 0 ==> coin::CoinSubAbortsIf { amount: amount_to_burn }; + include amount_to_burn > 0 ==> + coin::CoinSubAbortsIf { amount: amount_to_burn }; ensures coin.value == old(coin).value - amount_to_burn; } @@ -144,12 +151,14 @@ spec supra_framework::transaction_fee { use supra_framework::aggregator; let maybe_supply = coin::get_coin_supply_opt(); // property 6: Ensure the presence of the resource. - requires - (is_fees_collection_enabled() && option::is_some(maybe_supply)) ==> - (aggregator::spec_aggregator_get_val(global(@supra_framework).amount.value) <= - optional_aggregator::optional_aggregator_value( - option::spec_borrow(coin::get_coin_supply_opt()) - )); + requires (is_fees_collection_enabled() && option::is_some(maybe_supply)) ==> + ( + aggregator::spec_aggregator_get_val( + global(@supra_framework).amount.value + ) <= optional_aggregator::optional_aggregator_value( + option::spec_borrow(coin::get_coin_supply_opt()) + ) + ); } spec schema ProcessCollectedFeesRequiresAndEnsures { @@ -168,25 +177,31 @@ spec supra_framework::transaction_fee { let collected_fees = global(@supra_framework); let post post_collected_fees = global(@supra_framework); let pre_amount = aggregator::spec_aggregator_get_val(collected_fees.amount.value); - let post post_amount = aggregator::spec_aggregator_get_val(post_collected_fees.amount.value); + let post post_amount = aggregator::spec_aggregator_get_val( + post_collected_fees.amount.value + ); let fees_table = global(@supra_framework).fees_table; let post post_fees_table = global(@supra_framework).fees_table; let proposer = option::spec_borrow(collected_fees.proposer); let fee_to_add = pre_amount - pre_amount * collected_fees.burn_percentage / 100; - ensures is_fees_collection_enabled() ==> option::spec_is_none(post_collected_fees.proposer) && post_amount == 0; - ensures is_fees_collection_enabled() && aggregator::spec_read(collected_fees.amount.value) > 0 && - option::spec_is_some(collected_fees.proposer) ==> + ensures is_fees_collection_enabled() ==> + option::spec_is_none(post_collected_fees.proposer) && post_amount == 0; + ensures is_fees_collection_enabled() + && aggregator::spec_read(collected_fees.amount.value) > 0 + && option::spec_is_some(collected_fees.proposer) ==> if (proposer != @vm_reserved) { if (table::spec_contains(fees_table, proposer)) { - table::spec_get(post_fees_table, proposer).value == table::spec_get( - fees_table, - proposer - ).value + fee_to_add + table::spec_get(post_fees_table, proposer).value + == table::spec_get( + fees_table, + proposer + ).value + fee_to_add } else { table::spec_get(post_fees_table, proposer).value == fee_to_add } } else { - option::spec_is_none(post_collected_fees.proposer) && post_amount == 0 + option::spec_is_none(post_collected_fees.proposer) + && post_amount == 0 }; } @@ -216,8 +231,11 @@ spec supra_framework::transaction_fee { // modifies global>(account_addr); - aborts_if amount != 0 && !(exists>(aptos_addr) - && exists>(account_addr)); + aborts_if amount != 0 + && !( + exists>(aptos_addr) + && exists>(account_addr) + ); aborts_if coin_store.coin.value < amount; let maybe_supply = global>(aptos_addr).supply; @@ -275,22 +293,23 @@ spec supra_framework::transaction_fee { aborts_if !exists(@supra_framework); aborts_if fee > 0 && !exists>(account); aborts_if fee > 0 && coin_store.coin.value < fee; - aborts_if fee > 0 && aggregator::spec_aggregator_get_val(aggr) - + fee > aggregator::spec_get_limit(aggr); - aborts_if fee > 0 && aggregator::spec_aggregator_get_val(aggr) - + fee > MAX_U128; + aborts_if fee > 0 + && aggregator::spec_aggregator_get_val(aggr) + fee + > aggregator::spec_get_limit(aggr); + aborts_if fee > 0 && aggregator::spec_aggregator_get_val(aggr) + fee > MAX_U128; let post post_coin_store = global>(account); let post post_collected_fees = global(@supra_framework).amount; ensures post_coin_store.coin.value == coin_store.coin.value - fee; - ensures aggregator::spec_aggregator_get_val(post_collected_fees.value) == aggregator::spec_aggregator_get_val( - aggr - ) + fee; + ensures aggregator::spec_aggregator_get_val(post_collected_fees.value) + == aggregator::spec_aggregator_get_val(aggr) + fee; } /// Ensure caller is admin. /// Aborts if `SupraCoinCapabilities` already exists. - spec store_supra_coin_burn_cap(supra_framework: &signer, burn_cap: BurnCapability) { + spec store_supra_coin_burn_cap( + supra_framework: &signer, burn_cap: BurnCapability + ) { use std::signer; // TODO(fa_migration) @@ -302,12 +321,15 @@ spec supra_framework::transaction_fee { aborts_if exists(addr); aborts_if exists(addr); - ensures exists(addr) || exists(addr); + ensures exists(addr) + || exists(addr); } /// Ensure caller is admin. /// Aborts if `SupraCoinMintCapability` already exists. - spec store_supra_coin_mint_cap(supra_framework: &signer, mint_cap: MintCapability) { + spec store_supra_coin_mint_cap( + supra_framework: &signer, mint_cap: MintCapability + ) { use std::signer; let addr = signer::address_of(supra_framework); aborts_if !system_addresses::is_supra_framework_address(addr); diff --git a/aptos-move/framework/supra-framework/sources/transaction_validation.move b/aptos-move/framework/supra-framework/sources/transaction_validation.move index a8aa5efc1a01b..a7f080817b93c 100644 --- a/aptos-move/framework/supra-framework/sources/transaction_validation.move +++ b/aptos-move/framework/supra-framework/sources/transaction_validation.move @@ -25,7 +25,7 @@ module supra_framework::transaction_validation { // module_prologue_name is deprecated and not used. module_prologue_name: vector, multi_agent_prologue_name: vector, - user_epilogue_name: vector, + user_epilogue_name: vector } /// MSB is used to indicate a gas payer tx @@ -55,19 +55,22 @@ module supra_framework::transaction_validation { // module_prologue_name is deprecated and not used. module_prologue_name: vector, multi_agent_prologue_name: vector, - user_epilogue_name: vector, + user_epilogue_name: vector ) { system_addresses::assert_supra_framework(supra_framework); - move_to(supra_framework, TransactionValidation { - module_addr: @supra_framework, - module_name: b"transaction_validation", - script_prologue_name, - // module_prologue_name is deprecated and not used. - module_prologue_name, - multi_agent_prologue_name, - user_epilogue_name, - }); + move_to( + supra_framework, + TransactionValidation { + module_addr: @supra_framework, + module_name: b"transaction_validation", + script_prologue_name, + // module_prologue_name is deprecated and not used. + module_prologue_name, + multi_agent_prologue_name, + user_epilogue_name + } + ); } fun prologue_common( @@ -78,29 +81,34 @@ module supra_framework::transaction_validation { txn_gas_price: u64, txn_max_gas_units: u64, txn_expiration_time: u64, - chain_id: u8, + chain_id: u8 ) { assert!( timestamp::now_seconds() < txn_expiration_time, - error::invalid_argument(PROLOGUE_ETRANSACTION_EXPIRED), + error::invalid_argument(PROLOGUE_ETRANSACTION_EXPIRED) + ); + assert!( + chain_id::get() == chain_id, error::invalid_argument(PROLOGUE_EBAD_CHAIN_ID) ); - assert!(chain_id::get() == chain_id, error::invalid_argument(PROLOGUE_EBAD_CHAIN_ID)); let transaction_sender = signer::address_of(&sender); - if ( - transaction_sender == gas_payer - || account::exists_at(transaction_sender) - || !features::sponsored_automatic_account_creation_enabled() - || txn_sequence_number > 0 - ) { - assert!(account::exists_at(transaction_sender), error::invalid_argument(PROLOGUE_EACCOUNT_DOES_NOT_EXIST)); + if (transaction_sender == gas_payer + || account::exists_at(transaction_sender) + || !features::sponsored_automatic_account_creation_enabled() + || txn_sequence_number > 0) { assert!( - txn_authentication_key == account::get_authentication_key(transaction_sender), - error::invalid_argument(PROLOGUE_EINVALID_ACCOUNT_AUTH_KEY), + account::exists_at(transaction_sender), + error::invalid_argument(PROLOGUE_EACCOUNT_DOES_NOT_EXIST) + ); + assert!( + txn_authentication_key + == account::get_authentication_key(transaction_sender), + error::invalid_argument(PROLOGUE_EINVALID_ACCOUNT_AUTH_KEY) ); - let account_sequence_number = account::get_sequence_number(transaction_sender); + let account_sequence_number = + account::get_sequence_number(transaction_sender); assert!( txn_sequence_number < (1u64 << 63), error::out_of_range(PROLOGUE_ESEQUENCE_NUMBER_TOO_BIG) @@ -125,7 +133,7 @@ module supra_framework::transaction_validation { assert!( txn_authentication_key == bcs::to_bytes(&transaction_sender), - error::invalid_argument(PROLOGUE_EINVALID_ACCOUNT_AUTH_KEY), + error::invalid_argument(PROLOGUE_EINVALID_ACCOUNT_AUTH_KEY) ); }; @@ -133,7 +141,9 @@ module supra_framework::transaction_validation { if (features::operations_default_to_fa_supra_store_enabled()) { assert!( - supra_account::is_fungible_balance_at_least(gas_payer, max_transaction_fee), + supra_account::is_fungible_balance_at_least( + gas_payer, max_transaction_fee + ), error::invalid_argument(PROLOGUE_ECANT_PAY_GAS_DEPOSIT) ); } else { @@ -152,7 +162,7 @@ module supra_framework::transaction_validation { txn_max_gas_units: u64, txn_expiration_time: u64, chain_id: u8, - _script_hash: vector, + _script_hash: vector ) { let gas_payer = signer::address_of(&sender); prologue_common( @@ -176,7 +186,7 @@ module supra_framework::transaction_validation { txn_gas_price: u64, txn_max_gas_units: u64, txn_expiration_time: u64, - chain_id: u8, + chain_id: u8 ) { let sender_addr = signer::address_of(&sender); prologue_common( @@ -187,19 +197,22 @@ module supra_framework::transaction_validation { txn_gas_price, txn_max_gas_units, txn_expiration_time, - chain_id, + chain_id + ); + multi_agent_common_prologue( + secondary_signer_addresses, secondary_signer_public_key_hashes ); - multi_agent_common_prologue(secondary_signer_addresses, secondary_signer_public_key_hashes); } fun multi_agent_common_prologue( secondary_signer_addresses: vector
, - secondary_signer_public_key_hashes: vector>, + secondary_signer_public_key_hashes: vector> ) { let num_secondary_signers = vector::length(&secondary_signer_addresses); assert!( - vector::length(&secondary_signer_public_key_hashes) == num_secondary_signers, - error::invalid_argument(PROLOGUE_ESECONDARY_KEYS_ADDRESSES_COUNT_MISMATCH), + vector::length(&secondary_signer_public_key_hashes) + == num_secondary_signers, + error::invalid_argument(PROLOGUE_ESECONDARY_KEYS_ADDRESSES_COUNT_MISMATCH) ); let i = 0; @@ -209,17 +222,24 @@ module supra_framework::transaction_validation { invariant forall j in 0..i: account::exists_at(secondary_signer_addresses[j]) && secondary_signer_public_key_hashes[j] - == account::get_authentication_key(secondary_signer_addresses[j]); + == account::get_authentication_key( + secondary_signer_addresses[j] + ); }; (i < num_secondary_signers) }) { let secondary_address = *vector::borrow(&secondary_signer_addresses, i); - assert!(account::exists_at(secondary_address), error::invalid_argument(PROLOGUE_EACCOUNT_DOES_NOT_EXIST)); + assert!( + account::exists_at(secondary_address), + error::invalid_argument(PROLOGUE_EACCOUNT_DOES_NOT_EXIST) + ); - let signer_public_key_hash = *vector::borrow(&secondary_signer_public_key_hashes, i); + let signer_public_key_hash = + *vector::borrow(&secondary_signer_public_key_hashes, i); assert!( - signer_public_key_hash == account::get_authentication_key(secondary_address), - error::invalid_argument(PROLOGUE_EINVALID_ACCOUNT_AUTH_KEY), + signer_public_key_hash + == account::get_authentication_key(secondary_address), + error::invalid_argument(PROLOGUE_EINVALID_ACCOUNT_AUTH_KEY) ); i = i + 1; } @@ -236,9 +256,12 @@ module supra_framework::transaction_validation { txn_gas_price: u64, txn_max_gas_units: u64, txn_expiration_time: u64, - chain_id: u8, + chain_id: u8 ) { - assert!(features::fee_payer_enabled(), error::invalid_state(PROLOGUE_EFEE_PAYER_NOT_ENABLED)); + assert!( + features::fee_payer_enabled(), + error::invalid_state(PROLOGUE_EFEE_PAYER_NOT_ENABLED) + ); prologue_common( sender, fee_payer_address, @@ -247,12 +270,15 @@ module supra_framework::transaction_validation { txn_gas_price, txn_max_gas_units, txn_expiration_time, - chain_id, + chain_id + ); + multi_agent_common_prologue( + secondary_signer_addresses, secondary_signer_public_key_hashes ); - multi_agent_common_prologue(secondary_signer_addresses, secondary_signer_public_key_hashes); assert!( - fee_payer_public_key_hash == account::get_authentication_key(fee_payer_address), - error::invalid_argument(PROLOGUE_EINVALID_ACCOUNT_AUTH_KEY), + fee_payer_public_key_hash + == account::get_authentication_key(fee_payer_address), + error::invalid_argument(PROLOGUE_EINVALID_ACCOUNT_AUTH_KEY) ); } @@ -266,7 +292,14 @@ module supra_framework::transaction_validation { gas_units_remaining: u64 ) { let addr = signer::address_of(&account); - epilogue_gas_payer(account, addr, storage_fee_refunded, txn_gas_price, txn_max_gas_units, gas_units_remaining); + epilogue_gas_payer( + account, + addr, + storage_fee_refunded, + txn_gas_price, + txn_max_gas_units, + gas_units_remaining + ); } /// Epilogue function with explicit gas payer specified, is run after a transaction is successfully executed. @@ -279,7 +312,9 @@ module supra_framework::transaction_validation { txn_max_gas_units: u64, gas_units_remaining: u64 ) { - assert!(txn_max_gas_units >= gas_units_remaining, error::invalid_argument(EOUT_OF_GAS)); + assert!( + txn_max_gas_units >= gas_units_remaining, error::invalid_argument(EOUT_OF_GAS) + ); let gas_used = txn_max_gas_units - gas_units_remaining; assert!( @@ -292,30 +327,33 @@ module supra_framework::transaction_validation { // to do failed transaction cleanup. if (features::operations_default_to_fa_supra_store_enabled()) { assert!( - supra_account::is_fungible_balance_at_least(gas_payer, transaction_fee_amount), - error::out_of_range(PROLOGUE_ECANT_PAY_GAS_DEPOSIT), + supra_account::is_fungible_balance_at_least( + gas_payer, transaction_fee_amount + ), + error::out_of_range(PROLOGUE_ECANT_PAY_GAS_DEPOSIT) ); } else { assert!( coin::is_balance_at_least(gas_payer, transaction_fee_amount), - error::out_of_range(PROLOGUE_ECANT_PAY_GAS_DEPOSIT), + error::out_of_range(PROLOGUE_ECANT_PAY_GAS_DEPOSIT) ); }; - let amount_to_burn = if (features::collect_and_distribute_gas_fees()) { - // TODO(gas): We might want to distinguish the refundable part of the charge and burn it or track - // it separately, so that we don't increase the total supply by refunding. + let amount_to_burn = + if (features::collect_and_distribute_gas_fees()) { + // TODO(gas): We might want to distinguish the refundable part of the charge and burn it or track + // it separately, so that we don't increase the total supply by refunding. - // If transaction fees are redistributed to validators, collect them here for - // later redistribution. - transaction_fee::collect_fee(gas_payer, transaction_fee_amount); - 0 - } else { - // Otherwise, just burn the fee. - // TODO: this branch should be removed completely when transaction fee collection - // is tested and is fully proven to work well. - transaction_fee_amount - }; + // If transaction fees are redistributed to validators, collect them here for + // later redistribution. + transaction_fee::collect_fee(gas_payer, transaction_fee_amount); + 0 + } else { + // Otherwise, just burn the fee. + // TODO: this branch should be removed completely when transaction fee collection + // is tested and is fully proven to work well. + transaction_fee_amount + }; if (amount_to_burn > storage_fee_refunded) { let burn_amount = amount_to_burn - storage_fee_refunded; diff --git a/aptos-move/framework/supra-framework/sources/transaction_validation.spec.move b/aptos-move/framework/supra-framework/sources/transaction_validation.spec.move index 03e23c6c06dc7..9ba1f688e225f 100644 --- a/aptos-move/framework/supra-framework/sources/transaction_validation.spec.move +++ b/aptos-move/framework/supra-framework/sources/transaction_validation.spec.move @@ -31,11 +31,11 @@ spec supra_framework::transaction_validation { /// Ensure caller is `supra_framework`. /// Aborts if TransactionValidation already exists. spec initialize( - supra_framework: &signer, - script_prologue_name: vector, - module_prologue_name: vector, - multi_agent_prologue_name: vector, - user_epilogue_name: vector, + supra_framework: &signer, + script_prologue_name: vector, + module_prologue_name: vector, + multi_agent_prologue_name: vector, + user_epilogue_name: vector ) { use std::signer; let addr = signer::address_of(supra_framework); @@ -74,14 +74,26 @@ spec supra_framework::transaction_validation { || account::exists_at(transaction_sender) || transaction_sender == gas_payer || txn_sequence_number > 0 - ) && ( - !(txn_sequence_number >= global(transaction_sender).sequence_number) - || !(txn_authentication_key == global(transaction_sender).authentication_key) - || !account::exists_at(transaction_sender) - || !(txn_sequence_number == global(transaction_sender).sequence_number) - ); - - aborts_if features::spec_is_enabled(features::SPONSORED_AUTOMATIC_ACCOUNT_CREATION) + ) + && ( + !( + txn_sequence_number + >= global(transaction_sender).sequence_number + ) + || !( + txn_authentication_key + == global(transaction_sender).authentication_key + ) + || !account::exists_at(transaction_sender) + || !( + txn_sequence_number + == global(transaction_sender).sequence_number + ) + ); + + aborts_if features::spec_is_enabled( + features::SPONSORED_AUTOMATIC_ACCOUNT_CREATION + ) && transaction_sender != gas_payer && txn_sequence_number == 0 && !account::exists_at(transaction_sender) @@ -94,18 +106,20 @@ spec supra_framework::transaction_validation { aborts_if !exists>(gas_payer); // property 1: The sender of a transaction should have sufficient coin balance to pay the transaction fee. /// [high-level-req-1] - aborts_if !(global>(gas_payer).coin.value >= max_transaction_fee); + aborts_if !( + global>(gas_payer).coin.value >= max_transaction_fee + ); } spec prologue_common( - sender: signer, - gas_payer: address, - txn_sequence_number: u64, - txn_authentication_key: vector, - txn_gas_price: u64, - txn_max_gas_units: u64, - txn_expiration_time: u64, - chain_id: u8, + sender: signer, + gas_payer: address, + txn_sequence_number: u64, + txn_authentication_key: vector, + txn_gas_price: u64, + txn_max_gas_units: u64, + txn_expiration_time: u64, + chain_id: u8 ) { // TODO(fa_migration) pragma verify = false; @@ -113,14 +127,14 @@ spec supra_framework::transaction_validation { } spec script_prologue( - sender: signer, - txn_sequence_number: u64, - txn_public_key: vector, - txn_gas_price: u64, - txn_max_gas_units: u64, - txn_expiration_time: u64, - chain_id: u8, - _script_hash: vector, + sender: signer, + txn_sequence_number: u64, + txn_public_key: vector, + txn_gas_price: u64, + txn_max_gas_units: u64, + txn_expiration_time: u64, + chain_id: u8, + _script_hash: vector ) { // TODO(fa_migration) pragma verify = false; @@ -143,38 +157,38 @@ spec supra_framework::transaction_validation { /// [high-level-req-2] aborts_if exists i in 0..num_secondary_signers: !account::exists_at(secondary_signer_addresses[i]) - || secondary_signer_public_key_hashes[i] != - account::get_authentication_key(secondary_signer_addresses[i]); + || secondary_signer_public_key_hashes[i] + != account::get_authentication_key(secondary_signer_addresses[i]); // By the end, all secondary signers account should exist and public key hash should match. ensures forall i in 0..num_secondary_signers: account::exists_at(secondary_signer_addresses[i]) - && secondary_signer_public_key_hashes[i] == - account::get_authentication_key(secondary_signer_addresses[i]); + && secondary_signer_public_key_hashes[i] + == account::get_authentication_key(secondary_signer_addresses[i]); } spec multi_agent_common_prologue( - secondary_signer_addresses: vector
, - secondary_signer_public_key_hashes: vector>, + secondary_signer_addresses: vector
, + secondary_signer_public_key_hashes: vector> ) { include MultiAgentPrologueCommonAbortsIf { secondary_signer_addresses, - secondary_signer_public_key_hashes, + secondary_signer_public_key_hashes }; } /// Aborts if length of public key hashed vector /// not equal the number of singers. - spec multi_agent_script_prologue ( - sender: signer, - txn_sequence_number: u64, - txn_sender_public_key: vector, - secondary_signer_addresses: vector
, - secondary_signer_public_key_hashes: vector>, - txn_gas_price: u64, - txn_max_gas_units: u64, - txn_expiration_time: u64, - chain_id: u8, + spec multi_agent_script_prologue( + sender: signer, + txn_sequence_number: u64, + txn_sender_public_key: vector, + secondary_signer_addresses: vector
, + secondary_signer_public_key_hashes: vector>, + txn_gas_price: u64, + txn_max_gas_units: u64, + txn_expiration_time: u64, + chain_id: u8 ) { pragma verify_duration_estimate = 120; let gas_payer = signer::address_of(sender); @@ -183,26 +197,26 @@ spec supra_framework::transaction_validation { include PrologueCommonAbortsIf { gas_payer, txn_sequence_number, - txn_authentication_key: txn_sender_public_key, + txn_authentication_key: txn_sender_public_key }; include MultiAgentPrologueCommonAbortsIf { secondary_signer_addresses, - secondary_signer_public_key_hashes, + secondary_signer_public_key_hashes }; } spec fee_payer_script_prologue( - sender: signer, - txn_sequence_number: u64, - txn_sender_public_key: vector, - secondary_signer_addresses: vector
, - secondary_signer_public_key_hashes: vector>, - fee_payer_address: address, - fee_payer_public_key_hash: vector, - txn_gas_price: u64, - txn_max_gas_units: u64, - txn_expiration_time: u64, - chain_id: u8, + sender: signer, + txn_sequence_number: u64, + txn_sender_public_key: vector, + secondary_signer_addresses: vector
, + secondary_signer_public_key_hashes: vector>, + fee_payer_address: address, + fee_payer_public_key_hash: vector, + txn_gas_price: u64, + txn_max_gas_units: u64, + txn_expiration_time: u64, + chain_id: u8 ) { pragma verify_duration_estimate = 120; @@ -211,15 +225,17 @@ spec supra_framework::transaction_validation { include PrologueCommonAbortsIf { gas_payer, txn_sequence_number, - txn_authentication_key: txn_sender_public_key, + txn_authentication_key: txn_sender_public_key }; include MultiAgentPrologueCommonAbortsIf { secondary_signer_addresses, - secondary_signer_public_key_hashes, + secondary_signer_public_key_hashes }; aborts_if !account::exists_at(gas_payer); - aborts_if !(fee_payer_public_key_hash == account::get_authentication_key(gas_payer)); + aborts_if !( + fee_payer_public_key_hash == account::get_authentication_key(gas_payer) + ); aborts_if !features::spec_fee_payer_enabled(); } @@ -227,11 +243,11 @@ spec supra_framework::transaction_validation { /// `SupraCoinCapabilities` and `CoinInfo` should exists. /// Skip transaction_fee::burn_fee verification. spec epilogue( - account: signer, - storage_fee_refunded: u64, - txn_gas_price: u64, - txn_max_gas_units: u64, - gas_units_remaining: u64 + account: signer, + storage_fee_refunded: u64, + txn_gas_price: u64, + txn_max_gas_units: u64, + gas_units_remaining: u64 ) { // TODO(fa_migration) pragma verify = false; @@ -242,12 +258,12 @@ spec supra_framework::transaction_validation { /// `SupraCoinCapabilities` and `CoinInfo` should exist. /// Skip transaction_fee::burn_fee verification. spec epilogue_gas_payer( - account: signer, - gas_payer: address, - storage_fee_refunded: u64, - txn_gas_price: u64, - txn_max_gas_units: u64, - gas_units_remaining: u64 + account: signer, + gas_payer: address, + storage_fee_refunded: u64, + txn_gas_price: u64, + txn_max_gas_units: u64, + gas_units_remaining: u64 ) { // TODO(fa_migration) pragma verify = false; @@ -263,7 +279,11 @@ spec supra_framework::transaction_validation { use supra_framework::coin; use supra_framework::coin::{CoinStore, CoinInfo}; use supra_framework::optional_aggregator; - use supra_framework::transaction_fee::{SupraCoinCapabilities, SupraCoinMintCapability, CollectedFeesPerBlock}; + use supra_framework::transaction_fee::{ + SupraCoinCapabilities, + SupraCoinMintCapability, + CollectedFeesPerBlock + }; account: signer; gas_payer: address; @@ -293,23 +313,26 @@ spec supra_framework::transaction_validation { // ensures balance == pre_balance - transaction_fee_amount + storage_fee_refunded; ensures account.sequence_number == pre_account.sequence_number + 1; - // Check fee collection. - let collect_fee_enabled = features::spec_is_enabled(features::COLLECT_AND_DISTRIBUTE_GAS_FEES); + let collect_fee_enabled = features::spec_is_enabled( + features::COLLECT_AND_DISTRIBUTE_GAS_FEES + ); let collected_fees = global(@supra_framework).amount; let aggr = collected_fees.value; let aggr_val = aggregator::spec_aggregator_get_val(aggr); let aggr_lim = aggregator::spec_get_limit(aggr); /// [high-level-req-3] - aborts_if collect_fee_enabled && !exists(@supra_framework); - aborts_if collect_fee_enabled && transaction_fee_amount > 0 && aggr_val + transaction_fee_amount > aggr_lim; + aborts_if collect_fee_enabled + && !exists(@supra_framework); + aborts_if collect_fee_enabled + && transaction_fee_amount > 0 + && aggr_val + transaction_fee_amount > aggr_lim; // Check burning. // (Check the total supply aggregator when enabled.) - let amount_to_burn = if (collect_fee_enabled) { - 0 - } else { + let amount_to_burn = if (collect_fee_enabled) { 0 } + else { transaction_fee_amount - storage_fee_refunded }; let apt_addr = type_info::type_of().account_address; @@ -319,12 +342,18 @@ spec supra_framework::transaction_validation { let apt_supply_value = optional_aggregator::optional_aggregator_value(apt_supply); let post post_maybe_apt_supply = global>(apt_addr).supply; let post post_apt_supply = option::spec_borrow(post_maybe_apt_supply); - let post post_apt_supply_value = optional_aggregator::optional_aggregator_value(post_apt_supply); + let post post_apt_supply_value = optional_aggregator::optional_aggregator_value( + post_apt_supply + ); - aborts_if amount_to_burn > 0 && !exists(@supra_framework); + aborts_if amount_to_burn > 0 + && !exists(@supra_framework); aborts_if amount_to_burn > 0 && !exists>(apt_addr); - aborts_if amount_to_burn > 0 && total_supply_enabled && apt_supply_value < amount_to_burn; - ensures total_supply_enabled ==> apt_supply_value - amount_to_burn == post_apt_supply_value; + aborts_if amount_to_burn > 0 + && total_supply_enabled + && apt_supply_value < amount_to_burn; + ensures total_supply_enabled ==> + apt_supply_value - amount_to_burn == post_apt_supply_value; // Check minting. let amount_to_mint = if (collect_fee_enabled) { @@ -336,12 +365,15 @@ spec supra_framework::transaction_validation { let post post_total_supply = coin::supply; aborts_if amount_to_mint > 0 && !exists>(addr); - aborts_if amount_to_mint > 0 && !exists(@supra_framework); + aborts_if amount_to_mint > 0 + && !exists(@supra_framework); aborts_if amount_to_mint > 0 && total_supply + amount_to_mint > MAX_U128; - ensures amount_to_mint > 0 ==> post_total_supply == total_supply + amount_to_mint; + ensures amount_to_mint > 0 ==> + post_total_supply == total_supply + amount_to_mint; let aptos_addr = type_info::type_of().account_address; - aborts_if (amount_to_mint != 0) && !exists>(aptos_addr); + aborts_if (amount_to_mint != 0) + && !exists>(aptos_addr); include coin::CoinAddAbortsIf { amount: amount_to_mint }; } } diff --git a/aptos-move/framework/supra-framework/sources/validator_consensus_info.move b/aptos-move/framework/supra-framework/sources/validator_consensus_info.move index df338b8316570..e31139931bd7b 100644 --- a/aptos-move/framework/supra-framework/sources/validator_consensus_info.move +++ b/aptos-move/framework/supra-framework/sources/validator_consensus_info.move @@ -4,25 +4,18 @@ module supra_framework::validator_consensus_info { struct ValidatorConsensusInfo has copy, drop, store { addr: address, pk_bytes: vector, - voting_power: u64, + voting_power: u64 } /// Create a default `ValidatorConsensusInfo` object. Value may be invalid. Only for place holding prupose. public fun default(): ValidatorConsensusInfo { - ValidatorConsensusInfo { - addr: @vm, - pk_bytes: vector[], - voting_power: 0, - } + ValidatorConsensusInfo { addr: @vm, pk_bytes: vector[], voting_power: 0 } } /// Create a `ValidatorConsensusInfo` object. - public fun new(addr: address, pk_bytes: vector, voting_power: u64): ValidatorConsensusInfo { + public fun new(addr: address, pk_bytes: vector, voting_power: u64): ValidatorConsensusInfo { - addr, - pk_bytes, - voting_power, - } + ValidatorConsensusInfo { addr, pk_bytes, voting_power } } /// Get `ValidatorConsensusInfo.addr`. diff --git a/aptos-move/framework/supra-framework/sources/vesting.move b/aptos-move/framework/supra-framework/sources/vesting.move index a58e5492cd41a..731ff91f404ed 100644 --- a/aptos-move/framework/supra-framework/sources/vesting.move +++ b/aptos-move/framework/supra-framework/sources/vesting.move @@ -117,7 +117,7 @@ module supra_framework::vesting { period_duration: u64, // Last vesting period, 1-indexed. For example if 2 months have passed, the last vesting period, if distribution // was requested, would be 2. Default value is 0 which means there have been no vesting periods yet. - last_vested_period: u64, + last_vested_period: u64 } struct StakingInfo has store { @@ -128,7 +128,7 @@ module supra_framework::vesting { // The currently assigned voter. voter: address, // Commission paid to the operator of the stake pool. - commission_percentage: u64, + commission_percentage: u64 } struct VestingContract has key { @@ -155,19 +155,18 @@ module supra_framework::vesting { vest_events: EventHandle, distribute_events: EventHandle, terminate_events: EventHandle, - admin_withdraw_events: EventHandle, + admin_withdraw_events: EventHandle } struct VestingAccountManagement has key { - roles: SimpleMap, + roles: SimpleMap } struct AdminStore has key { vesting_contracts: vector
, // Used to create resource accounts for new vesting contracts so there's no address collision. nonce: u64, - - create_events: EventHandle, + create_events: EventHandle } #[event] @@ -178,7 +177,7 @@ module supra_framework::vesting { withdrawal_address: address, vesting_contract_address: address, staking_pool_address: address, - commission_percentage: u64, + commission_percentage: u64 } #[event] @@ -188,7 +187,7 @@ module supra_framework::vesting { staking_pool_address: address, old_operator: address, new_operator: address, - commission_percentage: u64, + commission_percentage: u64 } #[event] @@ -197,7 +196,7 @@ module supra_framework::vesting { vesting_contract_address: address, staking_pool_address: address, old_voter: address, - new_voter: address, + new_voter: address } #[event] @@ -205,7 +204,7 @@ module supra_framework::vesting { admin: address, vesting_contract_address: address, staking_pool_address: address, - new_lockup_expiration_secs: u64, + new_lockup_expiration_secs: u64 } #[event] @@ -214,7 +213,7 @@ module supra_framework::vesting { vesting_contract_address: address, shareholder: address, old_beneficiary: address, - new_beneficiary: address, + new_beneficiary: address } #[event] @@ -222,7 +221,7 @@ module supra_framework::vesting { admin: address, vesting_contract_address: address, staking_pool_address: address, - amount: u64, + amount: u64 } #[event] @@ -231,27 +230,27 @@ module supra_framework::vesting { vesting_contract_address: address, staking_pool_address: address, period_vested: u64, - amount: u64, + amount: u64 } #[event] struct Distribute has drop, store { admin: address, vesting_contract_address: address, - amount: u64, + amount: u64 } #[event] struct Terminate has drop, store { admin: address, - vesting_contract_address: address, + vesting_contract_address: address } #[event] struct AdminWithdraw has drop, store { admin: address, vesting_contract_address: address, - amount: u64, + amount: u64 } struct CreateVestingContractEvent has drop, store { @@ -261,7 +260,7 @@ module supra_framework::vesting { withdrawal_address: address, vesting_contract_address: address, staking_pool_address: address, - commission_percentage: u64, + commission_percentage: u64 } struct UpdateOperatorEvent has drop, store { @@ -270,7 +269,7 @@ module supra_framework::vesting { staking_pool_address: address, old_operator: address, new_operator: address, - commission_percentage: u64, + commission_percentage: u64 } struct UpdateVoterEvent has drop, store { @@ -278,14 +277,14 @@ module supra_framework::vesting { vesting_contract_address: address, staking_pool_address: address, old_voter: address, - new_voter: address, + new_voter: address } struct ResetLockupEvent has drop, store { admin: address, vesting_contract_address: address, staking_pool_address: address, - new_lockup_expiration_secs: u64, + new_lockup_expiration_secs: u64 } struct SetBeneficiaryEvent has drop, store { @@ -293,14 +292,14 @@ module supra_framework::vesting { vesting_contract_address: address, shareholder: address, old_beneficiary: address, - new_beneficiary: address, + new_beneficiary: address } struct UnlockRewardsEvent has drop, store { admin: address, vesting_contract_address: address, staking_pool_address: address, - amount: u64, + amount: u64 } struct VestEvent has drop, store { @@ -308,31 +307,33 @@ module supra_framework::vesting { vesting_contract_address: address, staking_pool_address: address, period_vested: u64, - amount: u64, + amount: u64 } struct DistributeEvent has drop, store { admin: address, vesting_contract_address: address, - amount: u64, + amount: u64 } struct TerminateEvent has drop, store { admin: address, - vesting_contract_address: address, + vesting_contract_address: address } struct AdminWithdrawEvent has drop, store { admin: address, vesting_contract_address: address, - amount: u64, + amount: u64 } #[view] /// Return the address of the underlying stake pool (separate resource account) of the vesting contract. /// /// This errors out if the vesting contract with the provided address doesn't exist. - public fun stake_pool_address(vesting_contract_address: address): address acquires VestingContract { + public fun stake_pool_address( + vesting_contract_address: address + ): address acquires VestingContract { assert_vesting_contract_exists(vesting_contract_address); borrow_global(vesting_contract_address).staking.pool_address } @@ -374,16 +375,22 @@ module supra_framework::vesting { /// This is the same as the shareholder address by default and only different if it's been explicitly set. /// /// This errors out if the vesting contract with the provided address doesn't exist. - public fun beneficiary(vesting_contract_address: address, shareholder: address): address acquires VestingContract { + public fun beneficiary( + vesting_contract_address: address, shareholder: address + ): address acquires VestingContract { assert_vesting_contract_exists(vesting_contract_address); - get_beneficiary(borrow_global(vesting_contract_address), shareholder) + get_beneficiary( + borrow_global(vesting_contract_address), shareholder + ) } #[view] /// Return the percentage of accumulated rewards that is paid to the operator as commission. /// /// This errors out if the vesting contract with the provided address doesn't exist. - public fun operator_commission_percentage(vesting_contract_address: address): u64 acquires VestingContract { + public fun operator_commission_percentage( + vesting_contract_address: address + ): u64 acquires VestingContract { assert_vesting_contract_exists(vesting_contract_address); borrow_global(vesting_contract_address).staking.commission_percentage } @@ -427,7 +434,9 @@ module supra_framework::vesting { /// So 268435456 = 0.0625. /// /// This errors out if the vesting contract with the provided address doesn't exist. - public fun vesting_schedule(vesting_contract_address: address): VestingSchedule acquires VestingContract { + public fun vesting_schedule( + vesting_contract_address: address + ): VestingSchedule acquires VestingContract { assert_vesting_contract_exists(vesting_contract_address); borrow_global(vesting_contract_address).vesting_schedule } @@ -437,12 +446,16 @@ module supra_framework::vesting { /// This excludes any unpaid commission that the operator has not collected. /// /// This errors out if the vesting contract with the provided address doesn't exist. - public fun total_accumulated_rewards(vesting_contract_address: address): u64 acquires VestingContract { + public fun total_accumulated_rewards( + vesting_contract_address: address + ): u64 acquires VestingContract { assert_active_vesting_contract(vesting_contract_address); let vesting_contract = borrow_global(vesting_contract_address); let (total_active_stake, _, commission_amount) = - staking_contract::staking_contract_amounts(vesting_contract_address, vesting_contract.staking.operator); + staking_contract::staking_contract_amounts( + vesting_contract_address, vesting_contract.staking.operator + ); total_active_stake - vesting_contract.remaining_grant - commission_amount } @@ -452,19 +465,26 @@ module supra_framework::vesting { /// /// This errors out if the vesting contract with the provided address doesn't exist. public fun accumulated_rewards( - vesting_contract_address: address, shareholder_or_beneficiary: address): u64 acquires VestingContract { + vesting_contract_address: address, shareholder_or_beneficiary: address + ): u64 acquires VestingContract { assert_active_vesting_contract(vesting_contract_address); - let total_accumulated_rewards = total_accumulated_rewards(vesting_contract_address); - let shareholder = shareholder(vesting_contract_address, shareholder_or_beneficiary); + let total_accumulated_rewards = + total_accumulated_rewards(vesting_contract_address); + let shareholder = + shareholder(vesting_contract_address, shareholder_or_beneficiary); let vesting_contract = borrow_global(vesting_contract_address); let shares = pool_u64::shares(&vesting_contract.grant_pool, shareholder); - pool_u64::shares_to_amount_with_total_coins(&vesting_contract.grant_pool, shares, total_accumulated_rewards) + pool_u64::shares_to_amount_with_total_coins( + &vesting_contract.grant_pool, shares, total_accumulated_rewards + ) } #[view] /// Return the list of all shareholders in the vesting contract. - public fun shareholders(vesting_contract_address: address): vector
acquires VestingContract { + public fun shareholders( + vesting_contract_address: address + ): vector
acquires VestingContract { assert_active_vesting_contract(vesting_contract_address); let vesting_contract = borrow_global(vesting_contract_address); @@ -478,8 +498,7 @@ module supra_framework::vesting { /// /// This returns 0x0 if no shareholder is found for the given beneficiary / the address is not a shareholder itself. public fun shareholder( - vesting_contract_address: address, - shareholder_or_beneficiary: address + vesting_contract_address: address, shareholder_or_beneficiary: address ): address acquires VestingContract { assert_active_vesting_contract(vesting_contract_address); @@ -489,14 +508,16 @@ module supra_framework::vesting { }; let vesting_contract = borrow_global(vesting_contract_address); let result = @0x0; - vector::any(shareholders, |shareholder| { - if (shareholder_or_beneficiary == get_beneficiary(vesting_contract, *shareholder)) { - result = *shareholder; - true - } else { - false + vector::any( + shareholders, + |shareholder| { + if (shareholder_or_beneficiary + == get_beneficiary(vesting_contract, *shareholder)) { + result = *shareholder; + true + } else { false } } - }); + ); result } @@ -505,20 +526,26 @@ module supra_framework::vesting { public fun create_vesting_schedule( schedule: vector, start_timestamp_secs: u64, - period_duration: u64, + period_duration: u64 ): VestingSchedule { - assert!(vector::length(&schedule) > 0, error::invalid_argument(EEMPTY_VESTING_SCHEDULE)); - assert!(period_duration > 0, error::invalid_argument(EZERO_VESTING_SCHEDULE_PERIOD)); + assert!( + vector::length(&schedule) > 0, error::invalid_argument( + EEMPTY_VESTING_SCHEDULE + ) + ); + assert!( + period_duration > 0, error::invalid_argument(EZERO_VESTING_SCHEDULE_PERIOD) + ); assert!( start_timestamp_secs >= timestamp::now_seconds(), - error::invalid_argument(EVESTING_START_TOO_SOON), + error::invalid_argument(EVESTING_START_TOO_SOON) ); VestingSchedule { schedule, start_timestamp_secs, period_duration, - last_vested_period: 0, + last_vested_period: 0 } } @@ -533,52 +560,68 @@ module supra_framework::vesting { voter: address, commission_percentage: u64, // Optional seed used when creating the staking contract account. - contract_creation_seed: vector, + contract_creation_seed: vector ): address acquires AdminStore { assert!( !system_addresses::is_reserved_address(withdrawal_address), - error::invalid_argument(EINVALID_WITHDRAWAL_ADDRESS), + error::invalid_argument(EINVALID_WITHDRAWAL_ADDRESS) ); assert_account_is_registered_for_supra(withdrawal_address); - assert!(vector::length(shareholders) > 0, error::invalid_argument(ENO_SHAREHOLDERS)); + assert!( + vector::length(shareholders) > 0, error::invalid_argument(ENO_SHAREHOLDERS) + ); assert!( simple_map::length(&buy_ins) == vector::length(shareholders), - error::invalid_argument(ESHARES_LENGTH_MISMATCH), + error::invalid_argument(ESHARES_LENGTH_MISMATCH) ); // Create a coins pool to track shareholders and shares of the grant. let grant = coin::zero(); let grant_amount = 0; let grant_pool = pool_u64::create(MAXIMUM_SHAREHOLDERS); - vector::for_each_ref(shareholders, |shareholder| { - let shareholder: address = *shareholder; - let (_, buy_in) = simple_map::remove(&mut buy_ins, &shareholder); - let buy_in_amount = coin::value(&buy_in); - coin::merge(&mut grant, buy_in); - pool_u64::buy_in( - &mut grant_pool, - shareholder, - buy_in_amount, - ); - grant_amount = grant_amount + buy_in_amount; - }); + vector::for_each_ref( + shareholders, + |shareholder| { + let shareholder: address = *shareholder; + let (_, buy_in) = simple_map::remove(&mut buy_ins, &shareholder); + let buy_in_amount = coin::value(&buy_in); + coin::merge(&mut grant, buy_in); + pool_u64::buy_in( + &mut grant_pool, + shareholder, + buy_in_amount + ); + grant_amount = grant_amount + buy_in_amount; + } + ); assert!(grant_amount > 0, error::invalid_argument(EZERO_GRANT)); // If this is the first time this admin account has created a vesting contract, initialize the admin store. let admin_address = signer::address_of(admin); if (!exists(admin_address)) { - move_to(admin, AdminStore { - vesting_contracts: vector::empty
(), - nonce: 0, - create_events: new_event_handle(admin), - }); + move_to( + admin, + AdminStore { + vesting_contracts: vector::empty
(), + nonce: 0, + create_events: new_event_handle(admin) + } + ); }; // Initialize the vesting contract in a new resource account. This allows the same admin to create multiple // pools. - let (contract_signer, contract_signer_cap) = create_vesting_contract_account(admin, contract_creation_seed); - let pool_address = staking_contract::create_staking_contract_with_coins( - &contract_signer, operator, voter, grant, commission_percentage, contract_creation_seed); + let (contract_signer, contract_signer_cap) = + create_vesting_contract_account(admin, contract_creation_seed); + let pool_address = + staking_contract::create_staking_contract_with_coins( + &contract_signer, + operator, + voter, + grant, + commission_percentage, + contract_creation_seed + ); // Add the newly created vesting contract's address to the admin store. let contract_address = signer::address_of(&contract_signer); @@ -593,8 +636,8 @@ module supra_framework::vesting { grant_amount, vesting_contract_address: contract_address, staking_pool_address: pool_address, - commission_percentage, - }, + commission_percentage + } ); }; emit_event( @@ -606,30 +649,46 @@ module supra_framework::vesting { grant_amount, vesting_contract_address: contract_address, staking_pool_address: pool_address, - commission_percentage, - }, + commission_percentage + } ); - move_to(&contract_signer, VestingContract { - state: VESTING_POOL_ACTIVE, - admin: admin_address, - grant_pool, - beneficiaries: simple_map::create(), - vesting_schedule, - withdrawal_address, - staking: StakingInfo { pool_address, operator, voter, commission_percentage }, - remaining_grant: grant_amount, - signer_cap: contract_signer_cap, - update_operator_events: new_event_handle(&contract_signer), - update_voter_events: new_event_handle(&contract_signer), - reset_lockup_events: new_event_handle(&contract_signer), - set_beneficiary_events: new_event_handle(&contract_signer), - unlock_rewards_events: new_event_handle(&contract_signer), - vest_events: new_event_handle(&contract_signer), - distribute_events: new_event_handle(&contract_signer), - terminate_events: new_event_handle(&contract_signer), - admin_withdraw_events: new_event_handle(&contract_signer), - }); + move_to( + &contract_signer, + VestingContract { + state: VESTING_POOL_ACTIVE, + admin: admin_address, + grant_pool, + beneficiaries: simple_map::create(), + vesting_schedule, + withdrawal_address, + staking: StakingInfo { + pool_address, + operator, + voter, + commission_percentage + }, + remaining_grant: grant_amount, + signer_cap: contract_signer_cap, + update_operator_events: new_event_handle( + &contract_signer + ), + update_voter_events: new_event_handle(&contract_signer), + reset_lockup_events: new_event_handle(&contract_signer), + set_beneficiary_events: new_event_handle( + &contract_signer + ), + unlock_rewards_events: new_event_handle( + &contract_signer + ), + vest_events: new_event_handle(&contract_signer), + distribute_events: new_event_handle(&contract_signer), + terminate_events: new_event_handle(&contract_signer), + admin_withdraw_events: new_event_handle( + &contract_signer + ) + } + ); simple_map::destroy_empty(buy_ins); contract_address @@ -643,15 +702,20 @@ module supra_framework::vesting { } /// Call `unlock_rewards` for many vesting contracts. - public entry fun unlock_rewards_many(contract_addresses: vector
) acquires VestingContract { + public entry fun unlock_rewards_many( + contract_addresses: vector
+ ) acquires VestingContract { let len = vector::length(&contract_addresses); assert!(len != 0, error::invalid_argument(EVEC_EMPTY_FOR_MANY_FUNCTION)); - vector::for_each_ref(&contract_addresses, |contract_address| { - let contract_address: address = *contract_address; - unlock_rewards(contract_address); - }); + vector::for_each_ref( + &contract_addresses, + |contract_address| { + let contract_address: address = *contract_address; + unlock_rewards(contract_address); + } + ); } /// Unlock any vested portion of the grant. @@ -663,35 +727,35 @@ module supra_framework::vesting { // expires. let vesting_contract = borrow_global_mut(contract_address); // Short-circuit if vesting hasn't started yet. - if (vesting_contract.vesting_schedule.start_timestamp_secs > timestamp::now_seconds()) { - return - }; + if (vesting_contract.vesting_schedule.start_timestamp_secs + > timestamp::now_seconds()) { return }; // Check if the next vested period has already passed. If not, short-circuit since there's nothing to vest. let vesting_schedule = &mut vesting_contract.vesting_schedule; let last_vested_period = vesting_schedule.last_vested_period; let next_period_to_vest = last_vested_period + 1; let last_completed_period = - (timestamp::now_seconds() - vesting_schedule.start_timestamp_secs) / vesting_schedule.period_duration; - if (last_completed_period < next_period_to_vest) { - return - }; + (timestamp::now_seconds() - vesting_schedule.start_timestamp_secs) + / vesting_schedule.period_duration; + if (last_completed_period < next_period_to_vest) { return }; // Calculate how much has vested, excluding rewards. // Index is 0-based while period is 1-based so we need to subtract 1. let schedule = &vesting_schedule.schedule; let schedule_index = next_period_to_vest - 1; - let vesting_fraction = if (schedule_index < vector::length(schedule)) { - *vector::borrow(schedule, schedule_index) - } else { - // Last vesting schedule fraction will repeat until the grant runs out. - *vector::borrow(schedule, vector::length(schedule) - 1) - }; + let vesting_fraction = + if (schedule_index < vector::length(schedule)) { + *vector::borrow(schedule, schedule_index) + } else { + // Last vesting schedule fraction will repeat until the grant runs out. + *vector::borrow(schedule, vector::length(schedule) - 1) + }; let total_grant = pool_u64::total_coins(&vesting_contract.grant_pool); let vested_amount = fixed_point32::multiply_u64(total_grant, vesting_fraction); // Cap vested amount by the remaining grant amount so we don't try to distribute more than what's remaining. vested_amount = min(vested_amount, vesting_contract.remaining_grant); - vesting_contract.remaining_grant = vesting_contract.remaining_grant - vested_amount; + vesting_contract.remaining_grant = vesting_contract.remaining_grant + - vested_amount; vesting_schedule.last_vested_period = next_period_to_vest; unlock_stake(vesting_contract, vested_amount); @@ -702,8 +766,8 @@ module supra_framework::vesting { vesting_contract_address: contract_address, staking_pool_address: vesting_contract.staking.pool_address, period_vested: next_period_to_vest, - amount: vested_amount, - }, + amount: vested_amount + } ); }; emit_event( @@ -713,8 +777,8 @@ module supra_framework::vesting { vesting_contract_address: contract_address, staking_pool_address: vesting_contract.staking.pool_address, period_vested: next_period_to_vest, - amount: vested_amount, - }, + amount: vested_amount + } ); } @@ -724,10 +788,13 @@ module supra_framework::vesting { assert!(len != 0, error::invalid_argument(EVEC_EMPTY_FOR_MANY_FUNCTION)); - vector::for_each_ref(&contract_addresses, |contract_address| { - let contract_address = *contract_address; - vest(contract_address); - }); + vector::for_each_ref( + &contract_addresses, + |contract_address| { + let contract_address = *contract_address; + vest(contract_address); + } + ); } /// Distribute any withdrawable stake from the stake pool. @@ -745,14 +812,20 @@ module supra_framework::vesting { // Distribute coins to all shareholders in the vesting contract. let grant_pool = &vesting_contract.grant_pool; let shareholders = &pool_u64::shareholders(grant_pool); - vector::for_each_ref(shareholders, |shareholder| { - let shareholder = *shareholder; - let shares = pool_u64::shares(grant_pool, shareholder); - let amount = pool_u64::shares_to_amount_with_total_coins(grant_pool, shares, total_distribution_amount); - let share_of_coins = coin::extract(&mut coins, amount); - let recipient_address = get_beneficiary(vesting_contract, shareholder); - supra_account::deposit_coins(recipient_address, share_of_coins); - }); + vector::for_each_ref( + shareholders, + |shareholder| { + let shareholder = *shareholder; + let shares = pool_u64::shares(grant_pool, shareholder); + let amount = + pool_u64::shares_to_amount_with_total_coins( + grant_pool, shares, total_distribution_amount + ); + let share_of_coins = coin::extract(&mut coins, amount); + let recipient_address = get_beneficiary(vesting_contract, shareholder); + supra_account::deposit_coins(recipient_address, share_of_coins); + } + ); // Send any remaining "dust" (leftover due to rounding error) to the withdrawal address. if (coin::value(&coins) > 0) { @@ -766,8 +839,8 @@ module supra_framework::vesting { Distribute { admin: vesting_contract.admin, vesting_contract_address: contract_address, - amount: total_distribution_amount, - }, + amount: total_distribution_amount + } ); }; emit_event( @@ -775,8 +848,8 @@ module supra_framework::vesting { DistributeEvent { admin: vesting_contract.admin, vesting_contract_address: contract_address, - amount: total_distribution_amount, - }, + amount: total_distribution_amount + } ); } @@ -786,14 +859,19 @@ module supra_framework::vesting { assert!(len != 0, error::invalid_argument(EVEC_EMPTY_FOR_MANY_FUNCTION)); - vector::for_each_ref(&contract_addresses, |contract_address| { - let contract_address = *contract_address; - distribute(contract_address); - }); + vector::for_each_ref( + &contract_addresses, + |contract_address| { + let contract_address = *contract_address; + distribute(contract_address); + } + ); } /// Terminate the vesting contract and send all funds back to the withdrawal address. - public entry fun terminate_vesting_contract(admin: &signer, contract_address: address) acquires VestingContract { + public entry fun terminate_vesting_contract( + admin: &signer, contract_address: address + ) acquires VestingContract { assert_active_vesting_contract(contract_address); // Distribute all withdrawable coins, which should have been from previous rewards withdrawal or vest. @@ -801,7 +879,8 @@ module supra_framework::vesting { let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); - let (active_stake, _, pending_active_stake, _) = stake::get_stake(vesting_contract.staking.pool_address); + let (active_stake, _, pending_active_stake, _) = + stake::get_stake(vesting_contract.staking.pool_address); assert!(pending_active_stake == 0, error::invalid_state(EPENDING_STAKE_FOUND)); // Unlock all remaining active stake. @@ -813,22 +892,24 @@ module supra_framework::vesting { emit( Terminate { admin: vesting_contract.admin, - vesting_contract_address: contract_address, - }, + vesting_contract_address: contract_address + } ); }; emit_event( &mut vesting_contract.terminate_events, TerminateEvent { admin: vesting_contract.admin, - vesting_contract_address: contract_address, - }, + vesting_contract_address: contract_address + } ); } /// Withdraw all funds to the preset vesting contract's withdrawal address. This can only be called if the contract /// has already been terminated. - public entry fun admin_withdraw(admin: &signer, contract_address: address) acquires VestingContract { + public entry fun admin_withdraw( + admin: &signer, contract_address: address + ) acquires VestingContract { let vesting_contract = borrow_global(contract_address); assert!( vesting_contract.state == VESTING_POOL_TERMINATED, @@ -850,8 +931,8 @@ module supra_framework::vesting { AdminWithdraw { admin: vesting_contract.admin, vesting_contract_address: contract_address, - amount, - }, + amount + } ); }; emit_event( @@ -859,8 +940,8 @@ module supra_framework::vesting { AdminWithdrawEvent { admin: vesting_contract.admin, vesting_contract_address: contract_address, - amount, - }, + amount + } ); } @@ -868,13 +949,15 @@ module supra_framework::vesting { admin: &signer, contract_address: address, new_operator: address, - commission_percentage: u64, + commission_percentage: u64 ) acquires VestingContract { let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); let contract_signer = &get_vesting_account_signer_internal(vesting_contract); let old_operator = vesting_contract.staking.operator; - staking_contract::switch_operator(contract_signer, old_operator, new_operator, commission_percentage); + staking_contract::switch_operator( + contract_signer, old_operator, new_operator, commission_percentage + ); vesting_contract.staking.operator = new_operator; vesting_contract.staking.commission_percentage = commission_percentage; @@ -886,8 +969,8 @@ module supra_framework::vesting { staking_pool_address: vesting_contract.staking.pool_address, old_operator, new_operator, - commission_percentage, - }, + commission_percentage + } ); }; emit_event( @@ -898,15 +981,15 @@ module supra_framework::vesting { staking_pool_address: vesting_contract.staking.pool_address, old_operator, new_operator, - commission_percentage, - }, + commission_percentage + } ); } public entry fun update_operator_with_same_commission( admin: &signer, contract_address: address, - new_operator: address, + new_operator: address ) acquires VestingContract { let commission_percentage = operator_commission_percentage(contract_address); update_operator(admin, contract_address, new_operator, commission_percentage); @@ -915,13 +998,15 @@ module supra_framework::vesting { public entry fun update_commission_percentage( admin: &signer, contract_address: address, - new_commission_percentage: u64, + new_commission_percentage: u64 ) acquires VestingContract { let operator = operator(contract_address); let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); let contract_signer = &get_vesting_account_signer_internal(vesting_contract); - staking_contract::update_commision(contract_signer, operator, new_commission_percentage); + staking_contract::update_commision( + contract_signer, operator, new_commission_percentage + ); vesting_contract.staking.commission_percentage = new_commission_percentage; // This function does not emit an event. Instead, `staking_contract::update_commission_percentage` // emits the event for this commission percentage update. @@ -930,13 +1015,15 @@ module supra_framework::vesting { public entry fun update_voter( admin: &signer, contract_address: address, - new_voter: address, + new_voter: address ) acquires VestingContract { let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); let contract_signer = &get_vesting_account_signer_internal(vesting_contract); let old_voter = vesting_contract.staking.voter; - staking_contract::update_voter(contract_signer, vesting_contract.staking.operator, new_voter); + staking_contract::update_voter( + contract_signer, vesting_contract.staking.operator, new_voter + ); vesting_contract.staking.voter = new_voter; if (std::features::module_event_migration_enabled()) { @@ -946,8 +1033,8 @@ module supra_framework::vesting { vesting_contract_address: contract_address, staking_pool_address: vesting_contract.staking.pool_address, old_voter, - new_voter, - }, + new_voter + } ); }; emit_event( @@ -957,14 +1044,13 @@ module supra_framework::vesting { vesting_contract_address: contract_address, staking_pool_address: vesting_contract.staking.pool_address, old_voter, - new_voter, - }, + new_voter + } ); } public entry fun reset_lockup( - admin: &signer, - contract_address: address, + admin: &signer, contract_address: address ) acquires VestingContract { let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); @@ -977,8 +1063,10 @@ module supra_framework::vesting { admin: vesting_contract.admin, vesting_contract_address: contract_address, staking_pool_address: vesting_contract.staking.pool_address, - new_lockup_expiration_secs: stake::get_lockup_secs(vesting_contract.staking.pool_address), - }, + new_lockup_expiration_secs: stake::get_lockup_secs( + vesting_contract.staking.pool_address + ) + } ); }; emit_event( @@ -987,8 +1075,10 @@ module supra_framework::vesting { admin: vesting_contract.admin, vesting_contract_address: contract_address, staking_pool_address: vesting_contract.staking.pool_address, - new_lockup_expiration_secs: stake::get_lockup_secs(vesting_contract.staking.pool_address), - }, + new_lockup_expiration_secs: stake::get_lockup_secs( + vesting_contract.staking.pool_address + ) + } ); } @@ -996,7 +1086,7 @@ module supra_framework::vesting { admin: &signer, contract_address: address, shareholder: address, - new_beneficiary: address, + new_beneficiary: address ) acquires VestingContract { // Verify that the beneficiary account is set up to receive SUPRA. This is a requirement so distribute() wouldn't // fail and block all other accounts from receiving SUPRA if one beneficiary is not registered. @@ -1021,8 +1111,8 @@ module supra_framework::vesting { vesting_contract_address: contract_address, shareholder, old_beneficiary, - new_beneficiary, - }, + new_beneficiary + } ); }; emit_event( @@ -1032,8 +1122,8 @@ module supra_framework::vesting { vesting_contract_address: contract_address, shareholder, old_beneficiary, - new_beneficiary, - }, + new_beneficiary + } ); } @@ -1042,14 +1132,15 @@ module supra_framework::vesting { public entry fun reset_beneficiary( account: &signer, contract_address: address, - shareholder: address, + shareholder: address ) acquires VestingAccountManagement, VestingContract { let vesting_contract = borrow_global_mut(contract_address); let addr = signer::address_of(account); assert!( - addr == vesting_contract.admin || - addr == get_role_holder(contract_address, utf8(ROLE_BENEFICIARY_RESETTER)), - error::permission_denied(EPERMISSION_DENIED), + addr == vesting_contract.admin + || addr + == get_role_holder(contract_address, utf8(ROLE_BENEFICIARY_RESETTER)), + error::permission_denied(EPERMISSION_DENIED) ); let beneficiaries = &mut vesting_contract.beneficiaries; @@ -1062,18 +1153,22 @@ module supra_framework::vesting { admin: &signer, contract_address: address, role: String, - role_holder: address, + role_holder: address ) acquires VestingAccountManagement, VestingContract { let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); if (!exists(contract_address)) { let contract_signer = &get_vesting_account_signer_internal(vesting_contract); - move_to(contract_signer, VestingAccountManagement { - roles: simple_map::create(), - }) + move_to( + contract_signer, + VestingAccountManagement { + roles: simple_map::create() + } + ) }; - let roles = &mut borrow_global_mut(contract_address).roles; + let roles = + &mut borrow_global_mut(contract_address).roles; if (simple_map::contains_key(roles, &role)) { *simple_map::borrow_mut(roles, &role) = role_holder; } else { @@ -1084,21 +1179,30 @@ module supra_framework::vesting { public entry fun set_beneficiary_resetter( admin: &signer, contract_address: address, - beneficiary_resetter: address, + beneficiary_resetter: address ) acquires VestingAccountManagement, VestingContract { - set_management_role(admin, contract_address, utf8(ROLE_BENEFICIARY_RESETTER), beneficiary_resetter); + set_management_role( + admin, + contract_address, + utf8(ROLE_BENEFICIARY_RESETTER), + beneficiary_resetter + ); } /// Set the beneficiary for the operator. public entry fun set_beneficiary_for_operator( - operator: &signer, - new_beneficiary: address, + operator: &signer, new_beneficiary: address ) { staking_contract::set_beneficiary_for_operator(operator, new_beneficiary); } - public fun get_role_holder(contract_address: address, role: String): address acquires VestingAccountManagement { - assert!(exists(contract_address), error::not_found(EVESTING_ACCOUNT_HAS_NO_ROLES)); + public fun get_role_holder( + contract_address: address, role: String + ): address acquires VestingAccountManagement { + assert!( + exists(contract_address), + error::not_found(EVESTING_ACCOUNT_HAS_NO_ROLES) + ); let roles = &borrow_global(contract_address).roles; assert!(simple_map::contains_key(roles, &role), error::not_found(EROLE_NOT_FOUND)); *simple_map::borrow(roles, &role) @@ -1107,21 +1211,24 @@ module supra_framework::vesting { /// For emergency use in case the admin needs emergency control of vesting contract account. /// This doesn't give the admin total power as the admin would still need to follow the rules set by /// staking_contract and stake modules. - public fun get_vesting_account_signer(admin: &signer, contract_address: address): signer acquires VestingContract { + public fun get_vesting_account_signer( + admin: &signer, contract_address: address + ): signer acquires VestingContract { let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); get_vesting_account_signer_internal(vesting_contract) } - fun get_vesting_account_signer_internal(vesting_contract: &VestingContract): signer { + fun get_vesting_account_signer_internal( + vesting_contract: &VestingContract + ): signer { account::create_signer_with_capability(&vesting_contract.signer_cap) } /// Create a salt for generating the resource accounts that will be holding the VestingContract. /// This address should be deterministic for the same admin and vesting contract creation nonce. fun create_vesting_contract_account( - admin: &signer, - contract_creation_seed: vector, + admin: &signer, contract_creation_seed: vector ): (signer, SignerCapability) acquires AdminStore { let admin_store = borrow_global_mut(signer::address_of(admin)); let seed = bcs::to_bytes(&signer::address_of(admin)); @@ -1142,25 +1249,38 @@ module supra_framework::vesting { } fun verify_admin(admin: &signer, vesting_contract: &VestingContract) { - assert!(signer::address_of(admin) == vesting_contract.admin, error::unauthenticated(ENOT_ADMIN)); + assert!( + signer::address_of(admin) == vesting_contract.admin, + error::unauthenticated(ENOT_ADMIN) + ); } fun assert_vesting_contract_exists(contract_address: address) { - assert!(exists(contract_address), error::not_found(EVESTING_CONTRACT_NOT_FOUND)); + assert!( + exists(contract_address), + error::not_found(EVESTING_CONTRACT_NOT_FOUND) + ); } fun assert_active_vesting_contract(contract_address: address) acquires VestingContract { assert_vesting_contract_exists(contract_address); let vesting_contract = borrow_global(contract_address); - assert!(vesting_contract.state == VESTING_POOL_ACTIVE, error::invalid_state(EVESTING_CONTRACT_NOT_ACTIVE)); + assert!( + vesting_contract.state == VESTING_POOL_ACTIVE, + error::invalid_state(EVESTING_CONTRACT_NOT_ACTIVE) + ); } fun unlock_stake(vesting_contract: &VestingContract, amount: u64) { let contract_signer = &get_vesting_account_signer_internal(vesting_contract); - staking_contract::unlock_stake(contract_signer, vesting_contract.staking.operator, amount); + staking_contract::unlock_stake( + contract_signer, vesting_contract.staking.operator, amount + ); } - fun withdraw_stake(vesting_contract: &VestingContract, contract_address: address): Coin { + fun withdraw_stake( + vesting_contract: &VestingContract, contract_address: address + ): Coin { // Claim any withdrawable distribution from the staking contract. The withdrawn coins will be sent directly to // the vesting contract's account. staking_contract::distribute(contract_address, vesting_contract.staking.operator); @@ -1224,14 +1344,21 @@ module supra_framework::vesting { 1000000 ); - vector::for_each_ref(accounts, |addr| { - let addr: address = *addr; - if (!account::exists_at(addr)) { - create_account(addr); - }; - }); + vector::for_each_ref( + accounts, + |addr| { + let addr: address = *addr; + if (!account::exists_at(addr)) { + create_account(addr); + }; + } + ); - std::features::change_feature_flags_for_testing(supra_framework, vector[MODULE_EVENT, OPERATOR_BENEFICIARY_CHANGE], vector[]); + std::features::change_feature_flags_for_testing( + supra_framework, + vector[MODULE_EVENT, OPERATOR_BENEFICIARY_CHANGE], + vector[] + ); } #[test_only] @@ -1240,7 +1367,7 @@ module supra_framework::vesting { shareholders: &vector
, shares: &vector, withdrawal_address: address, - commission_percentage: u64, + commission_percentage: u64 ): address acquires AdminStore { setup_vesting_contract_with_schedule( admin, @@ -1249,7 +1376,7 @@ module supra_framework::vesting { withdrawal_address, commission_percentage, &vector[3, 2, 1], - 48, + 48 ) } @@ -1261,24 +1388,34 @@ module supra_framework::vesting { withdrawal_address: address, commission_percentage: u64, vesting_numerators: &vector, - vesting_denominator: u64, + vesting_denominator: u64 ): address acquires AdminStore { let schedule = vector::empty(); - vector::for_each_ref(vesting_numerators, |num| { - vector::push_back(&mut schedule, fixed_point32::create_from_rational(*num, vesting_denominator)); - }); - let vesting_schedule = create_vesting_schedule( - schedule, - timestamp::now_seconds() + VESTING_SCHEDULE_CLIFF, - VESTING_PERIOD, + vector::for_each_ref( + vesting_numerators, + |num| { + vector::push_back( + &mut schedule, + fixed_point32::create_from_rational(*num, vesting_denominator) + ); + } ); + let vesting_schedule = + create_vesting_schedule( + schedule, + timestamp::now_seconds() + VESTING_SCHEDULE_CLIFF, + VESTING_PERIOD + ); let admin_address = signer::address_of(admin); let buy_ins = simple_map::create>(); - vector::enumerate_ref(shares, |i, share| { - let shareholder = *vector::borrow(shareholders, i); - simple_map::add(&mut buy_ins, shareholder, stake::mint_coins(*share)); - }); + vector::enumerate_ref( + shares, + |i, share| { + let shareholder = *vector::borrow(shareholders, i); + simple_map::add(&mut buy_ins, shareholder, stake::mint_coins(*share)); + } + ); create_vesting_contract( admin, @@ -1289,17 +1426,25 @@ module supra_framework::vesting { admin_address, admin_address, commission_percentage, - vector[], + vector[] ) } - #[test(supra_framework = @0x1, admin = @0x123, shareholder_1 = @0x234, shareholder_2 = @0x345, withdrawal = @111)] + #[ + test( + supra_framework = @0x1, + admin = @0x123, + shareholder_1 = @0x234, + shareholder_2 = @0x345, + withdrawal = @111 + ) + ] public entry fun test_end_to_end( supra_framework: &signer, admin: &signer, shareholder_1: &signer, shareholder_2: &signer, - withdrawal: &signer, + withdrawal: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let withdrawal_address = signer::address_of(withdrawal); @@ -1312,16 +1457,32 @@ module supra_framework::vesting { // Create the vesting contract. setup( - supra_framework, &vector[admin_address, withdrawal_address, shareholder_1_address, shareholder_2_address]); - let contract_address = setup_vesting_contract(admin, shareholders, shares, withdrawal_address, 0); - assert!(vector::length(&borrow_global(admin_address).vesting_contracts) == 1, 0); + supra_framework, + &vector[ + admin_address, + withdrawal_address, + shareholder_1_address, + shareholder_2_address + ] + ); + let contract_address = + setup_vesting_contract(admin, shareholders, shares, withdrawal_address, 0); + assert!( + vector::length(&borrow_global(admin_address).vesting_contracts) + == 1, + 0 + ); let stake_pool_address = stake_pool_address(contract_address); stake::assert_stake_pool(stake_pool_address, GRANT_AMOUNT, 0, 0, 0); // The stake pool is still in pending active stake, so unlock_rewards and vest shouldn't do anything. let (_sk, pk) = stake::generate_identity(); stake::join_validator_set_for_test(&pk, admin, stake_pool_address, false); - assert!(stake::get_validator_state(stake_pool_address) == VALIDATOR_STATUS_PENDING_ACTIVE, 1); + assert!( + stake::get_validator_state(stake_pool_address) + == VALIDATOR_STATUS_PENDING_ACTIVE, + 1 + ); unlock_rewards(contract_address); vest(contract_address); stake::assert_stake_pool(stake_pool_address, GRANT_AMOUNT, 0, 0, 0); @@ -1329,7 +1490,9 @@ module supra_framework::vesting { // Wait for the validator to join the validator set. No rewards are earnt yet so unlock_rewards and vest should // still do nothing. stake::end_epoch(); - assert!(stake::get_validator_state(stake_pool_address) == VALIDATOR_STATUS_ACTIVE, 2); + assert!( + stake::get_validator_state(stake_pool_address) == VALIDATOR_STATUS_ACTIVE, 2 + ); unlock_rewards(contract_address); vest(contract_address); stake::assert_stake_pool(stake_pool_address, GRANT_AMOUNT, 0, 0, 0); @@ -1375,8 +1538,13 @@ module supra_framework::vesting { let vested_amount = fraction(GRANT_AMOUNT, 3, 48); let remaining_grant = GRANT_AMOUNT - vested_amount; let pending_distribution = rewards + vested_amount; - assert!(remaining_grant(contract_address) == remaining_grant, remaining_grant(contract_address)); - stake::assert_stake_pool(stake_pool_address, remaining_grant, 0, 0, pending_distribution); + assert!( + remaining_grant(contract_address) == remaining_grant, + remaining_grant(contract_address) + ); + stake::assert_stake_pool( + stake_pool_address, remaining_grant, 0, 0, pending_distribution + ); // Fast forward to the end of the fourth period. We can call vest() 3 times to vest the last 3 periods. timestamp::fast_forward_seconds(VESTING_PERIOD * 3); @@ -1384,17 +1552,23 @@ module supra_framework::vesting { vested_amount = fraction(GRANT_AMOUNT, 2, 48); remaining_grant = remaining_grant - vested_amount; pending_distribution = pending_distribution + vested_amount; - stake::assert_stake_pool(stake_pool_address, remaining_grant, 0, 0, pending_distribution); + stake::assert_stake_pool( + stake_pool_address, remaining_grant, 0, 0, pending_distribution + ); vest(contract_address); vested_amount = fraction(GRANT_AMOUNT, 1, 48); remaining_grant = remaining_grant - vested_amount; pending_distribution = pending_distribution + vested_amount; - stake::assert_stake_pool(stake_pool_address, remaining_grant, 0, 0, pending_distribution); + stake::assert_stake_pool( + stake_pool_address, remaining_grant, 0, 0, pending_distribution + ); // The last vesting fraction (1/48) is repeated beyond the first 3 periods. vest(contract_address); remaining_grant = remaining_grant - vested_amount; pending_distribution = pending_distribution + vested_amount; - stake::assert_stake_pool(stake_pool_address, remaining_grant, 0, 0, pending_distribution); + stake::assert_stake_pool( + stake_pool_address, remaining_grant, 0, 0, pending_distribution + ); assert!(remaining_grant(contract_address) == remaining_grant, 0); stake::end_epoch(); @@ -1402,8 +1576,16 @@ module supra_framework::vesting { pending_distribution = with_rewards(pending_distribution); distribute(contract_address); stake::assert_stake_pool(stake_pool_address, total_active, 0, 0, 0); - assert!(coin::balance(shareholder_1_address) == shareholder_1_bal + pending_distribution / 4, 0); - assert!(coin::balance(shareholder_2_address) == shareholder_2_bal + pending_distribution * 3 / 4, 1); + assert!( + coin::balance(shareholder_1_address) + == shareholder_1_bal + pending_distribution / 4, + 0 + ); + assert!( + coin::balance(shareholder_2_address) + == shareholder_2_bal + pending_distribution * 3 / 4, + 1 + ); // Withdrawal address receives the left-over dust of 1 coin due to rounding error. assert!(coin::balance(withdrawal_address) == 1, 0); @@ -1416,14 +1598,17 @@ module supra_framework::vesting { stake::assert_stake_pool(stake_pool_address, 0, withdrawn_amount, 0, 0); let previous_bal = coin::balance(withdrawal_address); admin_withdraw(admin, contract_address); - assert!(coin::balance(withdrawal_address) == previous_bal + withdrawn_amount, 0); + assert!( + coin::balance(withdrawal_address) + == previous_bal + withdrawn_amount, + 0 + ); } #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x1000C, location = Self)] public entry fun test_create_vesting_contract_with_zero_grant_should_fail( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address]); @@ -1433,8 +1618,7 @@ module supra_framework::vesting { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x10004, location = Self)] public entry fun test_create_vesting_contract_with_no_shareholders_should_fail( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address]); @@ -1444,8 +1628,7 @@ module supra_framework::vesting { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x10005, location = Self)] public entry fun test_create_vesting_contract_with_mistmaching_shareholders_should_fail( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address]); @@ -1455,8 +1638,7 @@ module supra_framework::vesting { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x60001, location = supra_framework::supra_account)] public entry fun test_create_vesting_contract_with_invalid_withdrawal_address_should_fail( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address]); @@ -1466,8 +1648,7 @@ module supra_framework::vesting { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x60001, location = supra_framework::supra_account)] public entry fun test_create_vesting_contract_with_missing_withdrawal_account_should_fail( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address]); @@ -1477,8 +1658,7 @@ module supra_framework::vesting { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x60002, location = supra_framework::supra_account)] public entry fun test_create_vesting_contract_with_unregistered_withdrawal_account_should_fail( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address]); @@ -1488,40 +1668,53 @@ module supra_framework::vesting { #[test(supra_framework = @0x1)] #[expected_failure(abort_code = 0x10002, location = Self)] - public entry fun test_create_empty_vesting_schedule_should_fail(supra_framework: &signer) { + public entry fun test_create_empty_vesting_schedule_should_fail( + supra_framework: &signer + ) { setup(supra_framework, &vector[]); create_vesting_schedule(vector[], 1, 1); } #[test(supra_framework = @0x1)] #[expected_failure(abort_code = 0x10003, location = Self)] - public entry fun test_create_vesting_schedule_with_zero_period_duration_should_fail(supra_framework: &signer) { + public entry fun test_create_vesting_schedule_with_zero_period_duration_should_fail( + supra_framework: &signer + ) { setup(supra_framework, &vector[]); create_vesting_schedule(vector[fixed_point32::create_from_rational(1, 1)], 1, 0); } #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x10006, location = Self)] - public entry fun test_create_vesting_schedule_with_invalid_vesting_start_should_fail(supra_framework: &signer) { + public entry fun test_create_vesting_schedule_with_invalid_vesting_start_should_fail( + supra_framework: &signer + ) { setup(supra_framework, &vector[]); timestamp::update_global_time_for_test_secs(1000); create_vesting_schedule( vector[fixed_point32::create_from_rational(1, 1)], 900, - 1); + 1 + ); } #[test(supra_framework = @0x1, admin = @0x123, shareholder = @0x234)] public entry fun test_vest_twice_should_not_double_count( supra_framework: &signer, admin: &signer, - shareholder: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, &vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract( - admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0 + ); // Operator needs to join the validator set for the stake pool to earn rewards. let stake_pool_address = stake_pool_address(contract_address); @@ -1529,7 +1722,9 @@ module supra_framework::vesting { stake::join_validator_set_for_test(&pk, admin, stake_pool_address, true); // Fast forward to the end of the first period. vest() should now unlock 3/48 of the tokens. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + VESTING_PERIOD); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + VESTING_PERIOD + ); vest(contract_address); let vested_amount = fraction(GRANT_AMOUNT, 3, 48); let remaining_grant = GRANT_AMOUNT - vested_amount; @@ -1546,13 +1741,19 @@ module supra_framework::vesting { public entry fun test_unlock_rewards_twice_should_not_double_count( supra_framework: &signer, admin: &signer, - shareholder: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, &vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract( - admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0 + ); // Operator needs to join the validator set for the stake pool to earn rewards. let stake_pool_address = stake_pool_address(contract_address); @@ -1571,19 +1772,30 @@ module supra_framework::vesting { stake::assert_stake_pool(stake_pool_address, GRANT_AMOUNT, 0, 0, rewards); } - #[test(supra_framework = @0x1, admin = @0x123, shareholder = @0x234, operator = @0x345)] + #[test( + supra_framework = @0x1, admin = @0x123, shareholder = @0x234, operator = @0x345 + )] public entry fun test_unlock_rewards_should_pay_commission_first( supra_framework: &signer, admin: &signer, shareholder: &signer, - operator: &signer, + operator: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let operator_address = signer::address_of(operator); let shareholder_address = signer::address_of(shareholder); - setup(supra_framework, &vector[admin_address, shareholder_address, operator_address]); - let contract_address = setup_vesting_contract( - admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], admin_address, 0); + setup( + supra_framework, + &vector[admin_address, shareholder_address, operator_address] + ); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0 + ); assert!(operator_commission_percentage(contract_address) == 0, 0); // 10% commission will be paid to the operator. @@ -1601,7 +1813,9 @@ module supra_framework::vesting { let commission = accumulated_rewards / 10; // 10%. let staker_rewards = accumulated_rewards - commission; unlock_rewards(contract_address); - stake::assert_stake_pool(stake_pool_address, GRANT_AMOUNT, 0, 0, accumulated_rewards); + stake::assert_stake_pool( + stake_pool_address, GRANT_AMOUNT, 0, 0, accumulated_rewards + ); assert!(remaining_grant(contract_address) == GRANT_AMOUNT, 0); // Distribution should pay commission to operator first and remaining amount to shareholders. @@ -1614,7 +1828,8 @@ module supra_framework::vesting { 0 ); // Operator also earns more commission from the rewards earnt on the withdrawn rewards. - let commission_on_staker_rewards = (with_rewards(staker_rewards) - staker_rewards) / 10; + let commission_on_staker_rewards = + (with_rewards(staker_rewards) - staker_rewards) / 10; staker_rewards = with_rewards(staker_rewards) - commission_on_staker_rewards; commission = with_rewards(commission) + commission_on_staker_rewards; distribute(contract_address); @@ -1623,19 +1838,30 @@ module supra_framework::vesting { assert!(coin::balance(operator_address) == commission - 1, 1); } - #[test(supra_framework = @0x1, admin = @0x123, shareholder = @0x234, operator = @0x345)] + #[test( + supra_framework = @0x1, admin = @0x123, shareholder = @0x234, operator = @0x345 + )] public entry fun test_request_commission_should_not_lock_rewards_for_shareholders( supra_framework: &signer, admin: &signer, shareholder: &signer, - operator: &signer, + operator: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let operator_address = signer::address_of(operator); let shareholder_address = signer::address_of(shareholder); - setup(supra_framework, &vector[admin_address, shareholder_address, operator_address]); - let contract_address = setup_vesting_contract( - admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], admin_address, 0); + setup( + supra_framework, + &vector[admin_address, shareholder_address, operator_address] + ); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0 + ); assert!(operator_commission_percentage(contract_address) == 0, 0); // 10% commission will be paid to the operator. @@ -1658,7 +1884,9 @@ module supra_framework::vesting { // Unlock vesting rewards. This should still pay out the accumulated rewards to shareholders. unlock_rewards(contract_address); - stake::assert_stake_pool(stake_pool_address, GRANT_AMOUNT, 0, 0, accumulated_rewards); + stake::assert_stake_pool( + stake_pool_address, GRANT_AMOUNT, 0, 0, accumulated_rewards + ); assert!(remaining_grant(contract_address) == GRANT_AMOUNT, 0); // Distribution should pay commission to operator first and remaining amount to shareholders. @@ -1671,7 +1899,8 @@ module supra_framework::vesting { 0 ); // Operator also earns more commission from the rewards earnt on the withdrawn rewards. - let commission_on_staker_rewards = (with_rewards(staker_rewards) - staker_rewards) / 10; + let commission_on_staker_rewards = + (with_rewards(staker_rewards) - staker_rewards) / 10; staker_rewards = with_rewards(staker_rewards) - commission_on_staker_rewards; commission = with_rewards(commission) + commission_on_staker_rewards; distribute(contract_address); @@ -1684,31 +1913,44 @@ module supra_framework::vesting { public entry fun test_update_operator_with_same_commission( supra_framework: &signer, admin: &signer, - operator: &signer, + operator: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let operator_address = signer::address_of(operator); setup(supra_framework, &vector[admin_address, @11, operator_address]); - let contract_address = setup_vesting_contract( - admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 10); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 10 + ); update_operator_with_same_commission(admin, contract_address, operator_address); assert!(operator_commission_percentage(contract_address) == 10, 0); } - #[test(supra_framework = @0x1, admin = @0x123, shareholder = @0x234, operator = @0x345)] + #[test( + supra_framework = @0x1, admin = @0x123, shareholder = @0x234, operator = @0x345 + )] public entry fun test_commission_percentage_change( supra_framework: &signer, admin: &signer, shareholder: &signer, - operator: &signer, + operator: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let operator_address = signer::address_of(operator); let shareholder_address = signer::address_of(shareholder); - setup(supra_framework, &vector[admin_address, shareholder_address, operator_address]); - let contract_address = setup_vesting_contract( - admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], admin_address, 0); + setup( + supra_framework, + &vector[admin_address, shareholder_address, operator_address] + ); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0 + ); assert!(operator_commission_percentage(contract_address) == 0, 0); let stake_pool_address = stake_pool_address(contract_address); @@ -1724,10 +1966,10 @@ module supra_framework::vesting { // Stake pool earns some rewards. stake::end_epoch(); - let (_, accumulated_rewards, _) = staking_contract::staking_contract_amounts( - contract_address, - operator_address - ); + let (_, accumulated_rewards, _) = + staking_contract::staking_contract_amounts( + contract_address, operator_address + ); // Update commission percentage to 20%. This also immediately requests commission. update_commission_percentage(admin, contract_address, 20); @@ -1740,15 +1982,16 @@ module supra_framework::vesting { // Stake pool earns some more rewards. stake::end_epoch(); - let (_, accumulated_rewards, _) = staking_contract::staking_contract_amounts( - contract_address, - operator_address - ); + let (_, accumulated_rewards, _) = + staking_contract::staking_contract_amounts( + contract_address, operator_address + ); // Request commission again. staking_contract::request_commission(operator, contract_address, operator_address); // The commission is calculated using the current commission percentage which is 20%. - expected_commission = with_rewards(expected_commission) + (accumulated_rewards / 5); + expected_commission = with_rewards(expected_commission) + + (accumulated_rewards / 5); // Unlocks the commission. stake::fast_forward_to_unlock(stake_pool_address); @@ -1761,37 +2004,61 @@ module supra_framework::vesting { assert!(coin::balance(operator_address) == expected_commission, 1); } - #[test( - supra_framework = @0x1, - admin = @0x123, - shareholder = @0x234, - operator1 = @0x345, - beneficiary = @0x456, - operator2 = @0x567 - )] + #[ + test( + supra_framework = @0x1, + admin = @0x123, + shareholder = @0x234, + operator1 = @0x345, + beneficiary = @0x456, + operator2 = @0x567 + ) + ] public entry fun test_set_beneficiary_for_operator( supra_framework: &signer, admin: &signer, shareholder: &signer, operator1: &signer, beneficiary: &signer, - operator2: &signer, + operator2: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let operator_address1 = signer::address_of(operator1); let operator_address2 = signer::address_of(operator2); let shareholder_address = signer::address_of(shareholder); let beneficiary_address = signer::address_of(beneficiary); - setup(supra_framework, &vector[admin_address, shareholder_address, operator_address1, beneficiary_address]); - let contract_address = setup_vesting_contract( - admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], admin_address, 0); + setup( + supra_framework, + &vector[ + admin_address, + shareholder_address, + operator_address1, + beneficiary_address + ] + ); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0 + ); assert!(operator_commission_percentage(contract_address) == 0, 0); let stake_pool_address = stake_pool_address(contract_address); // 10% commission will be paid to the operator. update_operator(admin, contract_address, operator_address1, 10); - assert!(staking_contract::beneficiary_for_operator(operator_address1) == operator_address1, 0); + assert!( + staking_contract::beneficiary_for_operator(operator_address1) + == operator_address1, + 0 + ); set_beneficiary_for_operator(operator1, beneficiary_address); - assert!(staking_contract::beneficiary_for_operator(operator_address1) == beneficiary_address, 0); + assert!( + staking_contract::beneficiary_for_operator(operator_address1) + == beneficiary_address, + 0 + ); // Operator needs to join the validator set for the stake pool to earn rewards. let (_sk, pk) = stake::generate_identity(); @@ -1802,14 +2069,17 @@ module supra_framework::vesting { // Stake pool earns some rewards. stake::end_epoch(); - let (_, accumulated_rewards, _) = staking_contract::staking_contract_amounts(contract_address, - operator_address1 - ); + let (_, accumulated_rewards, _) = + staking_contract::staking_contract_amounts( + contract_address, operator_address1 + ); // Commission is calculated using the previous commission percentage which is 10%. let expected_commission = accumulated_rewards / 10; // Request commission. - staking_contract::request_commission(operator1, contract_address, operator_address1); + staking_contract::request_commission( + operator1, contract_address, operator_address1 + ); // Unlocks the commission. stake::fast_forward_to_unlock(stake_pool_address); expected_commission = with_rewards(expected_commission); @@ -1826,14 +2096,17 @@ module supra_framework::vesting { update_operator(admin, contract_address, operator_address2, 10); stake::end_epoch(); - let (_, accumulated_rewards, _) = staking_contract::staking_contract_amounts(contract_address, - operator_address2 - ); + let (_, accumulated_rewards, _) = + staking_contract::staking_contract_amounts( + contract_address, operator_address2 + ); let expected_commission = accumulated_rewards / 10; // Request commission. - staking_contract::request_commission(operator2, contract_address, operator_address2); + staking_contract::request_commission( + operator2, contract_address, operator_address2 + ); // Unlocks the commission. stake::fast_forward_to_unlock(stake_pool_address); expected_commission = with_rewards(expected_commission); @@ -1843,7 +2116,9 @@ module supra_framework::vesting { // Assert that the rewards go to operator2, and the balance of the operator1's beneficiay remains the same. assert!(coin::balance(operator_address2) >= expected_commission, 1); - assert!(coin::balance(beneficiary_address) == old_beneficiay_balance, 1); + assert!( + coin::balance(beneficiary_address) == old_beneficiay_balance, 1 + ); } #[test(supra_framework = @0x1, admin = @0x123, shareholder = @0x234)] @@ -1851,13 +2126,19 @@ module supra_framework::vesting { public entry fun test_cannot_unlock_rewards_after_contract_is_terminated( supra_framework: &signer, admin: &signer, - shareholder: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, &vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract( - admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0 + ); // Immediately terminate. Calling unlock_rewards should now fail. terminate_vesting_contract(admin, contract_address); @@ -1868,24 +2149,27 @@ module supra_framework::vesting { public entry fun test_vesting_contract_with_zero_vestings( supra_framework: &signer, admin: &signer, - shareholder: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, &vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract_with_schedule( - admin, - &vector[shareholder_address], - &vector[GRANT_AMOUNT], - admin_address, - 0, - &vector[0, 3, 0, 2], - 48, - ); + let contract_address = + setup_vesting_contract_with_schedule( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0, + &vector[0, 3, 0, 2], + 48 + ); let stake_pool_address = stake_pool_address(contract_address); // First vest() should unlock 0 according to schedule. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + VESTING_PERIOD); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + VESTING_PERIOD + ); vest(contract_address); stake::assert_stake_pool(stake_pool_address, GRANT_AMOUNT, 0, 0, 0); assert!(remaining_grant(contract_address) == GRANT_AMOUNT, 0); @@ -1919,25 +2203,28 @@ module supra_framework::vesting { public entry fun test_last_vest_should_distribute_remaining_amount( supra_framework: &signer, admin: &signer, - shareholder: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, &vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract_with_schedule( - admin, - &vector[shareholder_address], - &vector[GRANT_AMOUNT], - admin_address, - 0, - // First vest = 3/4 but last vest should only be for the remaining 1/4. - &vector[3], - 4, - ); + let contract_address = + setup_vesting_contract_with_schedule( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0, + // First vest = 3/4 but last vest should only be for the remaining 1/4. + &vector[3], + 4 + ); let stake_pool_address = stake_pool_address(contract_address); // First vest is 3/48 - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + VESTING_PERIOD); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + VESTING_PERIOD + ); vest(contract_address); let vested_amount = fraction(GRANT_AMOUNT, 3, 4); let remaining_grant = GRANT_AMOUNT - vested_amount; @@ -1960,13 +2247,19 @@ module supra_framework::vesting { public entry fun test_cannot_vest_after_contract_is_terminated( supra_framework: &signer, admin: &signer, - shareholder: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, &vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract( - admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0 + ); // Immediately terminate. Calling vest should now fail. terminate_vesting_contract(admin, contract_address); @@ -1978,13 +2271,19 @@ module supra_framework::vesting { public entry fun test_cannot_terminate_twice( supra_framework: &signer, admin: &signer, - shareholder: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, &vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract( - admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0 + ); // Call terminate_vesting_contract twice should fail. terminate_vesting_contract(admin, contract_address); @@ -1996,13 +2295,19 @@ module supra_framework::vesting { public entry fun test_cannot_call_admin_withdraw_if_contract_is_not_terminated( supra_framework: &signer, admin: &signer, - shareholder: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, &vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract( - admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + 0 + ); // Calling admin_withdraw should fail as contract has not been terminated. admin_withdraw(admin, contract_address); @@ -2011,44 +2316,57 @@ module supra_framework::vesting { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x60001, location = supra_framework::supra_account)] public entry fun test_set_beneficiary_with_missing_account_should_fail( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address]); - let contract_address = setup_vesting_contract( - admin, &vector[@1, @2], &vector[GRANT_AMOUNT, GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, + &vector[@1, @2], + &vector[GRANT_AMOUNT, GRANT_AMOUNT], + admin_address, + 0 + ); set_beneficiary(admin, contract_address, @1, @11); } #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x60002, location = supra_framework::supra_account)] public entry fun test_set_beneficiary_with_unregistered_account_should_fail( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address]); - let contract_address = setup_vesting_contract( - admin, &vector[@1, @2], &vector[GRANT_AMOUNT, GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, + &vector[@1, @2], + &vector[GRANT_AMOUNT, GRANT_AMOUNT], + admin_address, + 0 + ); create_account_for_test(@11); set_beneficiary(admin, contract_address, @1, @11); } #[test(supra_framework = @0x1, admin = @0x123)] public entry fun test_set_beneficiary_should_send_distribution( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address, @11]); - let contract_address = setup_vesting_contract( - admin, &vector[@1], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, &vector[@1], &vector[GRANT_AMOUNT], admin_address, 0 + ); set_beneficiary(admin, contract_address, @1, @11); assert!(beneficiary(contract_address, @1) == @11, 0); // Fast forward to the end of the first period. vest() should now unlock 3/48 of the tokens. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + VESTING_PERIOD); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + VESTING_PERIOD + ); vest(contract_address); // Distribution should go to the beneficiary account. @@ -2062,13 +2380,14 @@ module supra_framework::vesting { #[test(supra_framework = @0x1, admin = @0x123)] public entry fun test_set_management_role( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore, VestingAccountManagement, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address]); - let contract_address = setup_vesting_contract( - admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 0 + ); let role = utf8(b"RANDOM"); set_management_role(admin, contract_address, role, @12); assert!(get_role_holder(contract_address, role) == @12, 0); @@ -2078,18 +2397,21 @@ module supra_framework::vesting { #[test(supra_framework = @0x1, admin = @0x123)] public entry fun test_reset_beneficiary( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore, VestingAccountManagement, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address, @11, @12]); - let contract_address = setup_vesting_contract( - admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 0 + ); set_beneficiary(admin, contract_address, @11, @12); assert!(beneficiary(contract_address, @11) == @12, 0); // Fast forward to the end of the first period. vest() should now unlock 3/48 of the tokens. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + VESTING_PERIOD); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + VESTING_PERIOD + ); vest(contract_address); // Reset the beneficiary. @@ -2108,50 +2430,64 @@ module supra_framework::vesting { public entry fun test_reset_beneficiary_with_resetter_role( supra_framework: &signer, admin: &signer, - resetter: &signer, + resetter: &signer ) acquires AdminStore, VestingAccountManagement, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address, @11, @12]); - let contract_address = setup_vesting_contract( - admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 0 + ); set_beneficiary(admin, contract_address, @11, @12); assert!(beneficiary(contract_address, @11) == @12, 0); // Reset the beneficiary with the resetter role. let resetter_address = signer::address_of(resetter); set_beneficiary_resetter(admin, contract_address, resetter_address); - assert!(simple_map::length(&borrow_global(contract_address).roles) == 1, 0); + assert!( + simple_map::length( + &borrow_global(contract_address).roles + ) == 1, + 0 + ); reset_beneficiary(resetter, contract_address, @11); assert!(beneficiary(contract_address, @11) == @11, 0); } - #[test(supra_framework = @0x1, admin = @0x123, resetter = @0x234, random = @0x345)] + #[test( + supra_framework = @0x1, admin = @0x123, resetter = @0x234, random = @0x345 + )] #[expected_failure(abort_code = 0x5000F, location = Self)] public entry fun test_reset_beneficiary_with_unauthorized( supra_framework: &signer, admin: &signer, resetter: &signer, - random: &signer, + random: &signer ) acquires AdminStore, VestingAccountManagement, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address, @11]); - let contract_address = setup_vesting_contract( - admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 0 + ); // Reset the beneficiary with a random account. This should failed. set_beneficiary_resetter(admin, contract_address, signer::address_of(resetter)); reset_beneficiary(random, contract_address, @11); } - #[test(supra_framework = @0x1, admin = @0x123, resetter = @0x234, random = @0x345)] + #[test( + supra_framework = @0x1, admin = @0x123, resetter = @0x234, random = @0x345 + )] public entry fun test_shareholder( - supra_framework: &signer, - admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, &vector[admin_address, @11, @12]); - let contract_address = setup_vesting_contract( - admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 0); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address, 0 + ); // Confirm that the lookup returns the same address when a shareholder is // passed for which there is no beneficiary. @@ -2172,12 +2508,15 @@ module supra_framework::vesting { #[test_only] fun get_accumulated_rewards(contract_address: address): u64 acquires VestingContract { let vesting_contract = borrow_global(contract_address); - let (active_stake, _, _, _) = stake::get_stake(vesting_contract.staking.pool_address); + let (active_stake, _, _, _) = + stake::get_stake(vesting_contract.staking.pool_address); active_stake - vesting_contract.remaining_grant } #[test_only] fun fraction(total: u64, numerator: u64, denominator: u64): u64 { - fixed_point32::multiply_u64(total, fixed_point32::create_from_rational(numerator, denominator)) + fixed_point32::multiply_u64( + total, fixed_point32::create_from_rational(numerator, denominator) + ) } } diff --git a/aptos-move/framework/supra-framework/sources/vesting.spec.move b/aptos-move/framework/supra-framework/sources/vesting.spec.move index 0de9e9066db0b..97eeea504b482 100644 --- a/aptos-move/framework/supra-framework/sources/vesting.spec.move +++ b/aptos-move/framework/supra-framework/sources/vesting.spec.move @@ -109,7 +109,8 @@ spec supra_framework::vesting { // property 2: The vesting pool should not exceed a maximum of 30 shareholders. /// [high-level-spec-2] invariant forall a: address where exists(a): - global(a).grant_pool.shareholders_limit <= MAXIMUM_SHAREHOLDERS; + global(a).grant_pool.shareholders_limit + <= MAXIMUM_SHAREHOLDERS; } spec stake_pool_address(vesting_contract_address: address): address { @@ -166,9 +167,12 @@ spec supra_framework::vesting { // Note: commission percentage should not be under 0 or higher than 100, cause it's a percentage number // This requirement will solve the timeout issue of total_accumulated_rewards // However, accumulated_rewards is still timeout - requires staking_contract.commission_percentage >= 0 && staking_contract.commission_percentage <= 100; + requires staking_contract.commission_percentage >= 0 + && staking_contract.commission_percentage <= 100; - include ActiveVestingContractAbortsIf{contract_address: vesting_contract_address}; + include ActiveVestingContractAbortsIf { + contract_address: vesting_contract_address + }; let vesting_contract = global(vesting_contract_address); let staker = vesting_contract_address; @@ -185,17 +189,22 @@ spec supra_framework::vesting { let pending_active = coin::value(stake_pool.pending_active); let total_active_stake = active + pending_active; let accumulated_rewards = total_active_stake - staking_contract.principal; - let commission_amount = accumulated_rewards * staking_contract.commission_percentage / 100; + let commission_amount = accumulated_rewards + * staking_contract.commission_percentage / 100; aborts_if !exists(pool_address); aborts_if active + pending_active > MAX_U64; aborts_if total_active_stake < staking_contract.principal; - aborts_if accumulated_rewards * staking_contract.commission_percentage > MAX_U64; + aborts_if accumulated_rewards * staking_contract.commission_percentage + > MAX_U64; // This two item both contribute to the timeout - aborts_if (vesting_contract.remaining_grant + commission_amount) > total_active_stake; + aborts_if (vesting_contract.remaining_grant + commission_amount) + > total_active_stake; aborts_if total_active_stake < vesting_contract.remaining_grant; } - spec accumulated_rewards(vesting_contract_address: address, shareholder_or_beneficiary: address): u64 { + spec accumulated_rewards( + vesting_contract_address: address, shareholder_or_beneficiary: address + ): u64 { // TODO: A severe timeout can not be resolved. pragma verify = false; @@ -212,34 +221,47 @@ spec supra_framework::vesting { let pending_active = coin::value(stake_pool.pending_active); let total_active_stake = active + pending_active; let accumulated_rewards = total_active_stake - staking_contract.principal; - let commission_amount = accumulated_rewards * staking_contract.commission_percentage / 100; - let total_accumulated_rewards = total_active_stake - vesting_contract.remaining_grant - commission_amount; - - let shareholder = spec_shareholder(vesting_contract_address, shareholder_or_beneficiary); + let commission_amount = accumulated_rewards + * staking_contract.commission_percentage / 100; + let total_accumulated_rewards = total_active_stake + - vesting_contract.remaining_grant - commission_amount; + + let shareholder = spec_shareholder( + vesting_contract_address, shareholder_or_beneficiary + ); let pool = vesting_contract.grant_pool; let shares = pool_u64::spec_shares(pool, shareholder); - aborts_if pool.total_coins > 0 && pool.total_shares > 0 + aborts_if pool.total_coins > 0 + && pool.total_shares > 0 && (shares * total_accumulated_rewards) / pool.total_shares > MAX_U64; - ensures result == pool_u64::spec_shares_to_amount_with_total_coins(pool, shares, total_accumulated_rewards); + ensures result + == pool_u64::spec_shares_to_amount_with_total_coins( + pool, shares, total_accumulated_rewards + ); } spec shareholders(vesting_contract_address: address): vector
{ - include ActiveVestingContractAbortsIf{contract_address: vesting_contract_address}; + include ActiveVestingContractAbortsIf { + contract_address: vesting_contract_address + }; } - spec fun spec_shareholder(vesting_contract_address: address, shareholder_or_beneficiary: address): address; + spec fun spec_shareholder( + vesting_contract_address: address, shareholder_or_beneficiary: address + ): address; spec shareholder(vesting_contract_address: address, shareholder_or_beneficiary: address): address { pragma opaque; - include ActiveVestingContractAbortsIf{contract_address: vesting_contract_address}; - ensures [abstract] result == spec_shareholder(vesting_contract_address, shareholder_or_beneficiary); + include ActiveVestingContractAbortsIf { + contract_address: vesting_contract_address + }; + ensures [abstract] result + == spec_shareholder(vesting_contract_address, shareholder_or_beneficiary); } spec create_vesting_schedule( - schedule: vector, - start_timestamp_secs: u64, - period_duration: u64, + schedule: vector, start_timestamp_secs: u64, period_duration: u64 ): VestingSchedule { /// [high-level-req-6] aborts_if !(len(schedule) > 0); @@ -252,7 +274,8 @@ spec supra_framework::vesting { // TODO: Data invariant does not hold. pragma verify = false; /// [high-level-req-10] - aborts_if withdrawal_address == @supra_framework || withdrawal_address == @vm_reserved; + aborts_if withdrawal_address == @supra_framework + || withdrawal_address == @vm_reserved; aborts_if !exists(withdrawal_address); aborts_if !exists>(withdrawal_address); aborts_if len(shareholders) == 0; @@ -272,7 +295,9 @@ spec supra_framework::vesting { contract_address: address; // Cause timeout here - include TotalAccumulatedRewardsAbortsIf { vesting_contract_address: contract_address }; + include TotalAccumulatedRewardsAbortsIf { + vesting_contract_address: contract_address + }; let vesting_contract = global(contract_address); let operator = vesting_contract.staking.operator; @@ -284,8 +309,10 @@ spec supra_framework::vesting { let pending_active = coin::value(stake_pool.pending_active); let total_active_stake = active + pending_active; let accumulated_rewards = total_active_stake - staking_contract.principal; - let commission_amount = accumulated_rewards * staking_contract.commission_percentage / 100; - let amount = total_active_stake - vesting_contract.remaining_grant - commission_amount; + let commission_amount = accumulated_rewards + * staking_contract.commission_percentage / 100; + let amount = total_active_stake - vesting_contract.remaining_grant + - commission_amount; include UnlockStakeAbortsIf { vesting_contract, amount }; } @@ -313,8 +340,15 @@ spec supra_framework::vesting { spec schema PreconditionAbortsIf { contract_addresses: vector
; - requires forall i in 0..len(contract_addresses): simple_map::spec_get(global(contract_addresses[i]).staking_contracts, global(contract_addresses[i]).staking.operator).commission_percentage >= 0 - && simple_map::spec_get(global(contract_addresses[i]).staking_contracts, global(contract_addresses[i]).staking.operator).commission_percentage <= 100; + requires forall i in 0..len(contract_addresses): + simple_map::spec_get( + global(contract_addresses[i]).staking_contracts, + global(contract_addresses[i]).staking.operator + ).commission_percentage >= 0 + && simple_map::spec_get( + global(contract_addresses[i]).staking_contracts, + global(contract_addresses[i]).staking.operator + ).commission_percentage <= 100; } spec distribute(contract_address: address) { @@ -356,7 +390,7 @@ spec supra_framework::vesting { admin: &signer, contract_address: address, new_operator: address, - commission_percentage: u64, + commission_percentage: u64 ) { // TODO: Calls `staking_contract::switch_operator` which is not verified. pragma verify = false; @@ -366,35 +400,37 @@ spec supra_framework::vesting { let vesting_contract = global(contract_address); let acc = vesting_contract.signer_cap.account; let old_operator = vesting_contract.staking.operator; - include staking_contract::ContractExistsAbortsIf { staker: acc, operator: old_operator }; + include staking_contract::ContractExistsAbortsIf { + staker: acc, + operator: old_operator + }; let store = global(acc); let staking_contracts = store.staking_contracts; aborts_if simple_map::spec_contains_key(staking_contracts, new_operator); let staking_contract = simple_map::spec_get(staking_contracts, old_operator); - include DistributeInternalAbortsIf { staker: acc, operator: old_operator, staking_contract, distribute_events: store.distribute_events }; + include DistributeInternalAbortsIf { + staker: acc, + operator: old_operator, + staking_contract, + distribute_events: store.distribute_events + }; } spec update_operator_with_same_commission( - admin: &signer, - contract_address: address, - new_operator: address, + admin: &signer, contract_address: address, new_operator: address ) { pragma verify = false; } spec update_commission_percentage( - admin: &signer, - contract_address: address, - new_commission_percentage: u64, + admin: &signer, contract_address: address, new_commission_percentage: u64 ) { pragma verify = false; } spec update_voter( - admin: &signer, - contract_address: address, - new_voter: address, + admin: &signer, contract_address: address, new_voter: address ) { // TODO: set because of timeout (property proved) pragma verify_duration_estimate = 300; @@ -407,10 +443,7 @@ spec supra_framework::vesting { include staking_contract::UpdateVoterSchema; } - spec reset_lockup( - admin: &signer, - contract_address: address, - ) { + spec reset_lockup(admin: &signer, contract_address: address) { // TODO: set because of timeout (property proved) pragma verify_duration_estimate = 300; aborts_if !exists(contract_address); @@ -420,8 +453,8 @@ spec supra_framework::vesting { let operator = vesting_contract.staking.operator; let staker = vesting_contract.signer_cap.account; - include staking_contract::ContractExistsAbortsIf {staker, operator}; - include staking_contract::IncreaseLockupWithCapAbortsIf {staker, operator}; + include staking_contract::ContractExistsAbortsIf { staker, operator }; + include staking_contract::IncreaseLockupWithCapAbortsIf { staker, operator }; let store = global(staker); let staking_contract = simple_map::spec_get(store.staking_contracts, operator); @@ -433,7 +466,7 @@ spec supra_framework::vesting { admin: &signer, contract_address: address, shareholder: address, - new_beneficiary: address, + new_beneficiary: address ) { // TODO: set because of timeout (property proved) pragma verify_duration_estimate = 300; @@ -442,53 +475,49 @@ spec supra_framework::vesting { aborts_if !coin::spec_is_account_registered(new_beneficiary); include VerifyAdminAbortsIf; let post vesting_contract = global(contract_address); - ensures simple_map::spec_contains_key(vesting_contract.beneficiaries,shareholder); + ensures simple_map::spec_contains_key(vesting_contract.beneficiaries, shareholder); } spec reset_beneficiary( - account: &signer, - contract_address: address, - shareholder: address, + account: &signer, contract_address: address, shareholder: address ) { aborts_if !exists(contract_address); let addr = signer::address_of(account); let vesting_contract = global(contract_address); - aborts_if addr != vesting_contract.admin && !std::string::spec_internal_check_utf8(ROLE_BENEFICIARY_RESETTER); - aborts_if addr != vesting_contract.admin && !exists(contract_address); + aborts_if addr != vesting_contract.admin + && !std::string::spec_internal_check_utf8(ROLE_BENEFICIARY_RESETTER); + aborts_if addr != vesting_contract.admin + && !exists(contract_address); let roles = global(contract_address).roles; let role = std::string::spec_utf8(ROLE_BENEFICIARY_RESETTER); - aborts_if addr != vesting_contract.admin && !simple_map::spec_contains_key(roles, role); - aborts_if addr != vesting_contract.admin && addr != simple_map::spec_get(roles, role); + aborts_if addr != vesting_contract.admin + && !simple_map::spec_contains_key(roles, role); + aborts_if addr != vesting_contract.admin + && addr != simple_map::spec_get(roles, role); let post post_vesting_contract = global(contract_address); - ensures !simple_map::spec_contains_key(post_vesting_contract.beneficiaries,shareholder); + ensures !simple_map::spec_contains_key( + post_vesting_contract.beneficiaries, shareholder + ); } spec set_management_role( - admin: &signer, - contract_address: address, - role: String, - role_holder: address, + admin: &signer, contract_address: address, role: String, role_holder: address ) { pragma aborts_if_is_partial; include SetManagementRoleAbortsIf; } spec set_beneficiary_resetter( - admin: &signer, - contract_address: address, - beneficiary_resetter: address, + admin: &signer, contract_address: address, beneficiary_resetter: address ) { pragma aborts_if_is_partial; aborts_if !std::string::spec_internal_check_utf8(ROLE_BENEFICIARY_RESETTER); include SetManagementRoleAbortsIf; } - spec set_beneficiary_for_operator( - operator: &signer, - new_beneficiary: address, - ) { + spec set_beneficiary_for_operator(operator: &signer, new_beneficiary: address) { // TODO: temporary mockup pragma verify = false; } @@ -496,7 +525,7 @@ spec supra_framework::vesting { spec get_role_holder(contract_address: address, role: String): address { aborts_if !exists(contract_address); let roles = global(contract_address).roles; - aborts_if !simple_map::spec_contains_key(roles,role); + aborts_if !simple_map::spec_contains_key(roles, role); } spec get_vesting_account_signer(admin: &signer, contract_address: address): signer { @@ -509,10 +538,9 @@ spec supra_framework::vesting { spec fun spec_get_vesting_account_signer(vesting_contract: VestingContract): signer; - spec create_vesting_contract_account( - admin: &signer, - contract_creation_seed: vector, - ): (signer, SignerCapability) { + spec create_vesting_contract_account(admin: &signer, contract_creation_seed: vector): ( + signer, SignerCapability + ) { pragma verify_duration_estimate = 300; let admin_addr = signer::address_of(admin); let admin_store = global(admin_addr); @@ -529,15 +557,22 @@ spec supra_framework::vesting { aborts_if len(account::ZERO_AUTH_KEY) != 32; aborts_if admin_store.nonce + 1 > MAX_U64; let ea = account::exists_at(resource_addr); - include if (ea) account::CreateResourceAccountAbortsIf else account::CreateAccountAbortsIf {addr: resource_addr}; + include if (ea) account::CreateResourceAccountAbortsIf + else account::CreateAccountAbortsIf { addr: resource_addr }; let acc = global(resource_addr); let post post_acc = global(resource_addr); - aborts_if !exists>(resource_addr) && !aptos_std::type_info::spec_is_struct(); - aborts_if !exists>(resource_addr) && ea && acc.guid_creation_num + 2 > MAX_U64; - aborts_if !exists>(resource_addr) && ea && acc.guid_creation_num + 2 >= account::MAX_GUID_CREATION_NUM; - ensures exists(resource_addr) && post_acc.authentication_key == account::ZERO_AUTH_KEY && - exists>(resource_addr); + aborts_if !exists>(resource_addr) + && !aptos_std::type_info::spec_is_struct(); + aborts_if !exists>(resource_addr) + && ea + && acc.guid_creation_num + 2 > MAX_U64; + aborts_if !exists>(resource_addr) + && ea + && acc.guid_creation_num + 2 >= account::MAX_GUID_CREATION_NUM; + ensures exists(resource_addr) + && post_acc.authentication_key == account::ZERO_AUTH_KEY + && exists>(resource_addr); ensures signer::address_of(result_1) == resource_addr; ensures result_2.account == resource_addr; } @@ -569,15 +604,23 @@ spec supra_framework::vesting { // verify staking_contract::unlock_stake() let acc = vesting_contract.signer_cap.account; let operator = vesting_contract.staking.operator; - include amount != 0 ==> staking_contract::ContractExistsAbortsIf { staker: acc, operator }; + include amount != 0 ==> + staking_contract::ContractExistsAbortsIf { staker: acc, operator }; // verify staking_contract::distribute_internal() let store = global(acc); let staking_contract = simple_map::spec_get(store.staking_contracts, operator); - include amount != 0 ==> DistributeInternalAbortsIf { staker: acc, operator, staking_contract, distribute_events: store.distribute_events }; + include amount != 0 ==> + DistributeInternalAbortsIf { + staker: acc, + operator, + staking_contract, + distribute_events: store.distribute_events + }; } - spec withdraw_stake(vesting_contract: &VestingContract, contract_address: address): Coin { + spec withdraw_stake(vesting_contract: &VestingContract, contract_address: address): Coin< + SupraCoin> { // TODO: Calls `staking_contract::distribute` which is not verified. pragma verify = false; include WithdrawStakeAbortsIf; @@ -588,16 +631,24 @@ spec supra_framework::vesting { contract_address: address; let operator = vesting_contract.staking.operator; - include staking_contract::ContractExistsAbortsIf { staker: contract_address, operator }; + include staking_contract::ContractExistsAbortsIf { + staker: contract_address, + operator + }; // verify staking_contract::distribute_internal() let store = global(contract_address); let staking_contract = simple_map::spec_get(store.staking_contracts, operator); - include DistributeInternalAbortsIf { staker: contract_address, operator, staking_contract, distribute_events: store.distribute_events }; + include DistributeInternalAbortsIf { + staker: contract_address, + operator, + staking_contract, + distribute_events: store.distribute_events + }; } spec schema DistributeInternalAbortsIf { - staker: address; // The verification below does not contain the loop in staking_contract::update_distribution_pool(). + staker: address; // The verification below does not contain the loop in staking_contract::update_distribution_pool(). operator: address; staking_contract: staking_contract::StakingContract; distribute_events: EventHandle; @@ -616,13 +667,16 @@ spec supra_framework::vesting { let stake_pool_1 = global(pool_address_1); aborts_if !exists(@supra_framework); let validator_set = global(@supra_framework); - let inactive_state = !stake::spec_contains(validator_set.pending_active, pool_address_1) + let inactive_state = !stake::spec_contains( + validator_set.pending_active, pool_address_1 + ) && !stake::spec_contains(validator_set.active_validators, pool_address_1) && !stake::spec_contains(validator_set.pending_inactive, pool_address_1); let inactive_1 = stake_pool_1.inactive.value; let pending_inactive_1 = stake_pool_1.pending_inactive.value; let new_inactive_1 = inactive_1 + pending_inactive_1; - aborts_if inactive_state && timestamp::spec_now_seconds() >= stake_pool_1.locked_until_secs + aborts_if inactive_state + && timestamp::spec_now_seconds() >= stake_pool_1.locked_until_secs && inactive_1 + pending_inactive_1 > MAX_U64; } diff --git a/aptos-move/framework/supra-framework/sources/vesting_without_staking.move b/aptos-move/framework/supra-framework/sources/vesting_without_staking.move index d7ce38b49a833..645acec2756f4 100644 --- a/aptos-move/framework/supra-framework/sources/vesting_without_staking.move +++ b/aptos-move/framework/supra-framework/sources/vesting_without_staking.move @@ -82,13 +82,13 @@ module supra_framework::vesting_without_staking { period_duration: u64, // Last vesting period, 1-indexed. For example if 2 months have passed, the last vesting period, if distribution // was requested, would be 2. Default value is 0 which means there have been no vesting periods yet. - last_vested_period: u64, + last_vested_period: u64 } struct VestingRecord has copy, store, drop { init_amount: u64, left_amount: u64, - last_vested_period: u64, + last_vested_period: u64 } struct VestingContract has key { @@ -108,26 +108,24 @@ module supra_framework::vesting_without_staking { vest_events: EventHandle, terminate_events: EventHandle, admin_withdraw_events: EventHandle, - shareholder_removed_events: EventHandle, - + shareholder_removed_events: EventHandle } struct VestingAccountManagement has key { - roles: SimpleMap, + roles: SimpleMap } struct AdminStore has key { vesting_contracts: vector
, // Used to create resource accounts for new vesting contracts so there's no address collision. nonce: u64, - - create_events: EventHandle, + create_events: EventHandle } struct CreateVestingContractEvent has drop, store { grant_amount: u64, withdrawal_address: address, - vesting_contract_address: address, + vesting_contract_address: address } struct SetBeneficiaryEvent has drop, store { @@ -135,31 +133,31 @@ module supra_framework::vesting_without_staking { vesting_contract_address: address, shareholder: address, old_beneficiary: address, - new_beneficiary: address, + new_beneficiary: address } struct VestEvent has drop, store { admin: address, shareholder_address: address, vesting_contract_address: address, - period_vested: u64, + period_vested: u64 } struct TerminateEvent has drop, store { admin: address, - vesting_contract_address: address, + vesting_contract_address: address } struct AdminWithdrawEvent has drop, store { admin: address, vesting_contract_address: address, - amount: u64, + amount: u64 } struct ShareHolderRemovedEvent has drop, store { shareholder: address, beneficiary: Option
, - amount: u64, + amount: u64 } #[view] @@ -184,11 +182,14 @@ module supra_framework::vesting_without_staking { #[view] /// Return the remaining grant of shareholder - public fun remaining_grant(vesting_contract_address: address, shareholder_address: address) - : u64 acquires VestingContract { + public fun remaining_grant( + vesting_contract_address: address, shareholder_address: address + ): u64 acquires VestingContract { assert_vesting_contract_exists(vesting_contract_address); - simple_map::borrow(&borrow_global(vesting_contract_address).shareholders, - &shareholder_address).left_amount + simple_map::borrow( + &borrow_global(vesting_contract_address).shareholders, + &shareholder_address + ).left_amount } #[view] @@ -196,10 +197,13 @@ module supra_framework::vesting_without_staking { /// This is the same as the shareholder address by default and only different if it's been explicitly set. /// /// This errors out if the vesting contract with the provided address doesn't exist. - public fun beneficiary(vesting_contract_address: address, shareholder: address): address acquires VestingContract { + public fun beneficiary( + vesting_contract_address: address, shareholder: address + ): address acquires VestingContract { assert_vesting_contract_exists(vesting_contract_address); - get_beneficiary(borrow_global(vesting_contract_address), - shareholder) + get_beneficiary( + borrow_global(vesting_contract_address), shareholder + ) } #[view] @@ -222,14 +226,18 @@ module supra_framework::vesting_without_staking { /// So 268435456 = 0.0625. /// /// This errors out if the vesting contract with the provided address doesn't exist. - public fun vesting_schedule(vesting_contract_address: address): VestingSchedule acquires VestingContract { + public fun vesting_schedule( + vesting_contract_address: address + ): VestingSchedule acquires VestingContract { assert_vesting_contract_exists(vesting_contract_address); borrow_global(vesting_contract_address).vesting_schedule } #[view] /// Return the list of all shareholders in the vesting contract. - public fun shareholders(vesting_contract_address: address): vector
acquires VestingContract { + public fun shareholders( + vesting_contract_address: address + ): vector
acquires VestingContract { assert_active_vesting_contract(vesting_contract_address); let vesting_contract = borrow_global(vesting_contract_address); @@ -243,8 +251,9 @@ module supra_framework::vesting_without_staking { /// address is actually a shareholder address, just return the address back. /// /// This returns 0x0 if no shareholder is found for the given beneficiary / the address is not a shareholder itself. - public fun shareholder(vesting_contract_address: address, shareholder_or_beneficiary: address) - : address acquires VestingContract { + public fun shareholder( + vesting_contract_address: address, shareholder_or_beneficiary: address + ): address acquires VestingContract { assert_active_vesting_contract(vesting_contract_address); let shareholders = &shareholders(vesting_contract_address); @@ -263,31 +272,41 @@ module supra_framework::vesting_without_staking { /// Create a vesting schedule with the given schedule of distributions, a vesting start time and period duration. public fun create_vesting_schedule( - schedule: vector, start_timestamp_secs: u64, period_duration: u64, + schedule: vector, + start_timestamp_secs: u64, + period_duration: u64 ): VestingSchedule { let schedule_len = vector::length(&schedule); assert!(schedule_len > 0, error::invalid_argument(EEMPTY_VESTING_SCHEDULE)); // If the first vesting fraction is zero, we can replace it with nonzero by increasing start time - assert!(fixed_point32::get_raw_value(*vector::borrow(&schedule, 0)) != 0, - error::invalid_argument(EEMPTY_VESTING_SCHEDULE)); + assert!( + fixed_point32::get_raw_value(*vector::borrow(&schedule, 0)) != 0, + error::invalid_argument(EEMPTY_VESTING_SCHEDULE) + ); // last vesting fraction must be non zero to ensure that no amount remains unvested forever. - assert!(fixed_point32::get_raw_value(*vector::borrow(&schedule, schedule_len - 1)) - != 0, - error::invalid_argument(EEMPTY_VESTING_SCHEDULE)); + assert!( + fixed_point32::get_raw_value(*vector::borrow(&schedule, schedule_len - 1)) + != 0, + error::invalid_argument(EEMPTY_VESTING_SCHEDULE) + ); - assert!(period_duration > 0, error::invalid_argument(EZERO_VESTING_SCHEDULE_PERIOD)); - assert!(start_timestamp_secs >= timestamp::now_seconds(), - error::invalid_argument(EVESTING_START_TOO_SOON),); + assert!( + period_duration > 0, error::invalid_argument(EZERO_VESTING_SCHEDULE_PERIOD) + ); + assert!( + start_timestamp_secs >= timestamp::now_seconds(), + error::invalid_argument(EVESTING_START_TOO_SOON) + ); VestingSchedule { schedule, start_timestamp_secs, period_duration, - last_vested_period: 0, + last_vested_period: 0 } } - public entry fun create_vesting_contract_with_amounts ( + public entry fun create_vesting_contract_with_amounts( admin: &signer, shareholders: vector
, shares: vector, @@ -296,82 +315,105 @@ module supra_framework::vesting_without_staking { start_timestamp_secs: u64, period_duration: u64, withdrawal_address: address, - contract_creation_seed: vector, + contract_creation_seed: vector ) acquires AdminStore { - assert!(!system_addresses::is_reserved_address(withdrawal_address), - error::invalid_argument(EINVALID_WITHDRAWAL_ADDRESS),); + assert!( + !system_addresses::is_reserved_address(withdrawal_address), + error::invalid_argument(EINVALID_WITHDRAWAL_ADDRESS) + ); assert_account_is_registered_for_supra(withdrawal_address); - assert!(vector::length(&shareholders) > 0, - error::invalid_argument(ENO_SHAREHOLDERS)); + assert!( + vector::length(&shareholders) > 0, error::invalid_argument(ENO_SHAREHOLDERS) + ); assert!( vector::length(&shareholders) == vector::length(&shares), - error::invalid_argument(ESHARES_LENGTH_MISMATCH), + error::invalid_argument(ESHARES_LENGTH_MISMATCH) ); // If this is the first time this admin account has created a vesting contract, initialize the admin store. let admin_address = signer::address_of(admin); if (!exists(admin_address)) { - move_to(admin, + move_to( + admin, AdminStore { vesting_contracts: vector::empty
(), nonce: 0, - create_events: new_event_handle(admin), - }); + create_events: new_event_handle(admin) + } + ); }; // Initialize the vesting contract in a new resource account. This allows the same admin to create multiple // pools. - let (contract_signer, contract_signer_cap) = create_vesting_contract_account(admin, - contract_creation_seed); + let (contract_signer, contract_signer_cap) = + create_vesting_contract_account(admin, contract_creation_seed); let contract_signer_address = signer::address_of(&contract_signer); - let schedule = vector::map_ref(&vesting_numerators, |numerator| { - let event = fixed_point32::create_from_rational(*numerator, vesting_denominator); - event - }); + let schedule = vector::map_ref( + &vesting_numerators, + |numerator| { + let event = + fixed_point32::create_from_rational(*numerator, vesting_denominator); + event + } + ); - let vesting_schedule = create_vesting_schedule(schedule, start_timestamp_secs, period_duration); + let vesting_schedule = + create_vesting_schedule(schedule, start_timestamp_secs, period_duration); let shareholders_map = simple_map::create(); let grant_amount = 0; - vector::for_each_reverse(shares, |amount| { - let shareholder = vector::pop_back(&mut shareholders); - simple_map::add(&mut shareholders_map, - shareholder, - VestingRecord { - init_amount: amount, - left_amount: amount, - last_vested_period: vesting_schedule.last_vested_period, - } - ); - grant_amount = grant_amount + amount; - }); + vector::for_each_reverse( + shares, + |amount| { + let shareholder = vector::pop_back(&mut shareholders); + simple_map::add( + &mut shareholders_map, + shareholder, + VestingRecord { + init_amount: amount, + left_amount: amount, + last_vested_period: vesting_schedule.last_vested_period + } + ); + grant_amount = grant_amount + amount; + } + ); assert!(grant_amount > 0, error::invalid_argument(EZERO_GRANT)); coin::transfer(admin, contract_signer_address, grant_amount); let admin_store = borrow_global_mut(admin_address); vector::push_back(&mut admin_store.vesting_contracts, contract_signer_address); - emit_event(&mut admin_store.create_events, + emit_event( + &mut admin_store.create_events, CreateVestingContractEvent { withdrawal_address, grant_amount, - vesting_contract_address: contract_signer_address, - }, + vesting_contract_address: contract_signer_address + } ); - move_to(&contract_signer, + move_to( + &contract_signer, VestingContract { state: VESTING_POOL_ACTIVE, admin: admin_address, - shareholders:shareholders_map, + shareholders: shareholders_map, beneficiaries: simple_map::create(), vesting_schedule, withdrawal_address, signer_cap: contract_signer_cap, - set_beneficiary_events: new_event_handle(&contract_signer), + set_beneficiary_events: new_event_handle( + &contract_signer + ), vest_events: new_event_handle(&contract_signer), terminate_events: new_event_handle(&contract_signer), - admin_withdraw_events: new_event_handle(&contract_signer), - shareholder_removed_events: new_event_handle(&contract_signer), - }); + admin_withdraw_events: new_event_handle( + &contract_signer + ), + shareholder_removed_events: new_event_handle( + &contract_signer + ) + } + ); } /// Create a vesting contract with a given configurations. @@ -380,14 +422,18 @@ module supra_framework::vesting_without_staking { buy_ins: SimpleMap>, vesting_schedule: VestingSchedule, withdrawal_address: address, - contract_creation_seed: vector, + contract_creation_seed: vector ): address acquires AdminStore { - assert!(!system_addresses::is_reserved_address(withdrawal_address), - error::invalid_argument(EINVALID_WITHDRAWAL_ADDRESS),); + assert!( + !system_addresses::is_reserved_address(withdrawal_address), + error::invalid_argument(EINVALID_WITHDRAWAL_ADDRESS) + ); assert_account_is_registered_for_supra(withdrawal_address); let shareholders_address = &simple_map::keys(&buy_ins); - assert!(vector::length(shareholders_address) > 0, - error::invalid_argument(ENO_SHAREHOLDERS)); + assert!( + vector::length(shareholders_address) > 0, + error::invalid_argument(ENO_SHAREHOLDERS) + ); let shareholders = simple_map::create(); let grant = coin::zero(); @@ -398,12 +444,13 @@ module supra_framework::vesting_without_staking { let buy_in = vector::pop_back(&mut buy_ins); let init = coin::value(&buy_in); coin::merge(&mut grant, buy_in); - simple_map::add(&mut shareholders, + simple_map::add( + &mut shareholders, shareholder, VestingRecord { init_amount: init, left_amount: init, - last_vested_period: vesting_schedule.last_vested_period, + last_vested_period: vesting_schedule.last_vested_period } ); grant_amount = grant_amount + init; @@ -413,32 +460,36 @@ module supra_framework::vesting_without_staking { // If this is the first time this admin account has created a vesting contract, initialize the admin store. let admin_address = signer::address_of(admin); if (!exists(admin_address)) { - move_to(admin, + move_to( + admin, AdminStore { vesting_contracts: vector::empty
(), nonce: 0, - create_events: new_event_handle(admin), - }); + create_events: new_event_handle(admin) + } + ); }; // Initialize the vesting contract in a new resource account. This allows the same admin to create multiple // pools. - let (contract_signer, contract_signer_cap) = create_vesting_contract_account(admin, - contract_creation_seed); + let (contract_signer, contract_signer_cap) = + create_vesting_contract_account(admin, contract_creation_seed); let contract_signer_address = signer::address_of(&contract_signer); coin::deposit(contract_signer_address, grant); let admin_store = borrow_global_mut(admin_address); vector::push_back(&mut admin_store.vesting_contracts, contract_signer_address); - emit_event(&mut admin_store.create_events, + emit_event( + &mut admin_store.create_events, CreateVestingContractEvent { withdrawal_address, grant_amount, - vesting_contract_address: contract_signer_address, - }, + vesting_contract_address: contract_signer_address + } ); - move_to(&contract_signer, + move_to( + &contract_signer, VestingContract { state: VESTING_POOL_ACTIVE, admin: admin_address, @@ -447,12 +498,19 @@ module supra_framework::vesting_without_staking { vesting_schedule, withdrawal_address, signer_cap: contract_signer_cap, - set_beneficiary_events: new_event_handle(&contract_signer), + set_beneficiary_events: new_event_handle( + &contract_signer + ), vest_events: new_event_handle(&contract_signer), terminate_events: new_event_handle(&contract_signer), - admin_withdraw_events: new_event_handle(&contract_signer), - shareholder_removed_events: new_event_handle(&contract_signer), - }); + admin_withdraw_events: new_event_handle( + &contract_signer + ), + shareholder_removed_events: new_event_handle( + &contract_signer + ) + } + ); vector::destroy_empty(buy_ins); contract_signer_address @@ -463,7 +521,8 @@ module supra_framework::vesting_without_staking { assert_active_vesting_contract(contract_address); let vesting_contract = borrow_global_mut(contract_address); // Short-circuit if vesting hasn't started yet. - if (vesting_contract.vesting_schedule.start_timestamp_secs > timestamp::now_seconds()) { return }; + if (vesting_contract.vesting_schedule.start_timestamp_secs + > timestamp::now_seconds()) { return }; let shareholders = simple_map::keys(&vesting_contract.shareholders); while (vector::length(&shareholders) > 0) { @@ -476,16 +535,22 @@ module supra_framework::vesting_without_staking { }; } - public entry fun vest_individual(contract_address: address, shareholder_address: address) acquires VestingContract { + public entry fun vest_individual( + contract_address: address, shareholder_address: address + ) acquires VestingContract { //check if contract exist, active and shareholder is a member of the contract assert_shareholder_exists(contract_address, shareholder_address); let vesting_contract = borrow_global_mut(contract_address); let beneficiary = get_beneficiary(vesting_contract, shareholder_address); // Short-circuit if vesting hasn't started yet. - if (vesting_contract.vesting_schedule.start_timestamp_secs > timestamp::now_seconds()) { return }; + if (vesting_contract.vesting_schedule.start_timestamp_secs + > timestamp::now_seconds()) { return }; - let vesting_record = simple_map::borrow_mut(&mut vesting_contract.shareholders, &shareholder_address); + let vesting_record = + simple_map::borrow_mut( + &mut vesting_contract.shareholders, &shareholder_address + ); let signer_cap = &vesting_contract.signer_cap; // Check if the next vested period has already passed. If not, short-circuit since there's nothing to vest. @@ -493,27 +558,31 @@ module supra_framework::vesting_without_staking { let schedule = &vesting_schedule.schedule; let last_vested_period = vesting_record.last_vested_period; let next_period_to_vest = last_vested_period + 1; - let last_completed_period = (timestamp::now_seconds() - vesting_schedule.start_timestamp_secs) - / vesting_schedule.period_duration; + let last_completed_period = + (timestamp::now_seconds() - vesting_schedule.start_timestamp_secs) + / vesting_schedule.period_duration; // Index is 0-based while period is 1-based so we need to subtract 1. - while (last_completed_period >= next_period_to_vest && vesting_record.left_amount > 0) { + while (last_completed_period >= next_period_to_vest + && vesting_record.left_amount > 0) { let schedule_index = next_period_to_vest - 1; - let vesting_fraction = if (schedule_index < vector::length(schedule)) { - *vector::borrow(schedule, schedule_index) - } else { - // Last vesting schedule fraction will repeat until the grant runs out. - *vector::borrow(schedule, vector::length(schedule) - 1) - }; + let vesting_fraction = + if (schedule_index < vector::length(schedule)) { + *vector::borrow(schedule, schedule_index) + } else { + // Last vesting schedule fraction will repeat until the grant runs out. + *vector::borrow(schedule, vector::length(schedule) - 1) + }; vest_transfer(vesting_record, signer_cap, beneficiary, vesting_fraction); - emit_event(&mut vesting_contract.vest_events, + emit_event( + &mut vesting_contract.vest_events, VestEvent { admin: vesting_contract.admin, shareholder_address: shareholder_address, vesting_contract_address: contract_address, - period_vested: next_period_to_vest, - }, + period_vested: next_period_to_vest + } ); next_period_to_vest = next_period_to_vest + 1; }; @@ -531,8 +600,11 @@ module supra_framework::vesting_without_staking { let vesting_signer = account::create_signer_with_capability(signer_cap); //amount to be transfer is minimum of what is left and vesting fraction due of init_amount - let amount = min(vesting_record.left_amount, - fixed_point32::multiply_u64(vesting_record.init_amount, vesting_fraction)); + let amount = + min( + vesting_record.left_amount, + fixed_point32::multiply_u64(vesting_record.init_amount, vesting_fraction) + ); //update left_amount for the shareholder vesting_record.left_amount = vesting_record.left_amount - amount; coin::transfer(&vesting_signer, beneficiary, amount); @@ -547,43 +619,50 @@ module supra_framework::vesting_without_staking { let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); let vesting_signer = get_vesting_account_signer_internal(vesting_contract); - let shareholder_amount = simple_map::borrow(&vesting_contract.shareholders, &shareholder_address) - .left_amount; - coin::transfer(&vesting_signer, vesting_contract.withdrawal_address, - shareholder_amount); - emit_event(&mut vesting_contract.admin_withdraw_events, + let shareholder_amount = + simple_map::borrow(&vesting_contract.shareholders, &shareholder_address).left_amount; + coin::transfer( + &vesting_signer, vesting_contract.withdrawal_address, shareholder_amount + ); + emit_event( + &mut vesting_contract.admin_withdraw_events, AdminWithdrawEvent { admin: vesting_contract.admin, vesting_contract_address: contract_address, - amount: shareholder_amount, - }, + amount: shareholder_amount + } ); // remove `shareholder_address`` from `vesting_contract.shareholders` let shareholders = &mut vesting_contract.shareholders; - let (_, shareholders_vesting) = simple_map::remove(shareholders, &shareholder_address); + let (_, shareholders_vesting) = + simple_map::remove(shareholders, &shareholder_address); // remove `shareholder_address` from `vesting_contract.beneficiaries` let beneficiary = option::none(); let shareholder_beneficiaries = &mut vesting_contract.beneficiaries; // Not all shareholders have their beneficiaries, so before removing them, we need to check if the beneficiary exists if (simple_map::contains_key(shareholder_beneficiaries, &shareholder_address)) { - let (_, shareholder_baneficiary) = simple_map::remove(shareholder_beneficiaries, &shareholder_address); + let (_, shareholder_baneficiary) = + simple_map::remove(shareholder_beneficiaries, &shareholder_address); beneficiary = option::some(shareholder_baneficiary); }; // Emit ShareHolderRemovedEvent - emit_event(&mut vesting_contract.shareholder_removed_events, + emit_event( + &mut vesting_contract.shareholder_removed_events, ShareHolderRemovedEvent { shareholder: shareholder_address, beneficiary, - amount: shareholders_vesting.left_amount, - }, + amount: shareholders_vesting.left_amount + } ); } /// Terminate the vesting contract and send all funds back to the withdrawal address. - public entry fun terminate_vesting_contract(admin: &signer, contract_address: address) acquires VestingContract { + public entry fun terminate_vesting_contract( + admin: &signer, contract_address: address + ) acquires VestingContract { assert_active_vesting_contract(contract_address); vest(contract_address); @@ -593,35 +672,45 @@ module supra_framework::vesting_without_staking { // Distribute remaining coins to withdrawal address of vesting contract. let shareholders_address = simple_map::keys(&vesting_contract.shareholders); - vector::for_each_ref(&shareholders_address, + vector::for_each_ref( + &shareholders_address, |shareholder| { - let shareholder_amount = simple_map::borrow_mut(&mut vesting_contract.shareholders, - shareholder); + let shareholder_amount = + simple_map::borrow_mut( + &mut vesting_contract.shareholders, shareholder + ); shareholder_amount.left_amount = 0; - }); + } + ); set_terminate_vesting_contract(contract_address); } /// Withdraw all funds to the preset vesting contract's withdrawal address. This can only be called if the contract /// has already been terminated. - public entry fun admin_withdraw(admin: &signer, contract_address: address) acquires VestingContract { + public entry fun admin_withdraw( + admin: &signer, contract_address: address + ) acquires VestingContract { let vesting_contract = borrow_global(contract_address); - assert!(vesting_contract.state == VESTING_POOL_TERMINATED, - error::invalid_state(EVESTING_CONTRACT_STILL_ACTIVE)); + assert!( + vesting_contract.state == VESTING_POOL_TERMINATED, + error::invalid_state(EVESTING_CONTRACT_STILL_ACTIVE) + ); let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); let total_balance = coin::balance(contract_address); let vesting_signer = get_vesting_account_signer_internal(vesting_contract); - coin::transfer(&vesting_signer, vesting_contract.withdrawal_address, - total_balance); + coin::transfer( + &vesting_signer, vesting_contract.withdrawal_address, total_balance + ); - emit_event(&mut vesting_contract.admin_withdraw_events, + emit_event( + &mut vesting_contract.admin_withdraw_events, AdminWithdrawEvent { admin: vesting_contract.admin, vesting_contract_address: contract_address, - amount: total_balance, - }, + amount: total_balance + } ); } @@ -629,7 +718,7 @@ module supra_framework::vesting_without_staking { admin: &signer, contract_address: address, shareholder: address, - new_beneficiary: address, + new_beneficiary: address ) acquires VestingContract { // Verify that the beneficiary account is set up to receive SUPRA. This is a requirement so distribute() wouldn't // fail and block all other accounts from receiving SUPRA if one beneficiary is not registered. @@ -642,27 +731,35 @@ module supra_framework::vesting_without_staking { let beneficiaries = &mut vesting_contract.beneficiaries; simple_map::upsert(beneficiaries, shareholder, new_beneficiary); - emit_event(&mut vesting_contract.set_beneficiary_events, + emit_event( + &mut vesting_contract.set_beneficiary_events, SetBeneficiaryEvent { admin: vesting_contract.admin, vesting_contract_address: contract_address, shareholder, old_beneficiary, - new_beneficiary, - }, + new_beneficiary + } ); } /// Remove the beneficiary for the given shareholder. All distributions will sent directly to the shareholder /// account. public entry fun reset_beneficiary( - account: &signer, contract_address: address, shareholder: address, + account: &signer, + contract_address: address, + shareholder: address ) acquires VestingAccountManagement, VestingContract { let vesting_contract = borrow_global_mut(contract_address); let addr = signer::address_of(account); - assert!(addr == vesting_contract.admin || addr == get_role_holder(contract_address, - utf8(ROLE_BENEFICIARY_RESETTER)), - error::permission_denied(EPERMISSION_DENIED),); + assert!( + addr == vesting_contract.admin + || addr + == get_role_holder( + contract_address, utf8(ROLE_BENEFICIARY_RESETTER) + ), + error::permission_denied(EPERMISSION_DENIED) + ); let beneficiaries = &mut vesting_contract.beneficiaries; if (simple_map::contains_key(beneficiaries, &shareholder)) { @@ -674,50 +771,70 @@ module supra_framework::vesting_without_staking { admin: &signer, contract_address: address, role: String, - role_holder: address, + role_holder: address ) acquires VestingAccountManagement, VestingContract { let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); if (!exists(contract_address)) { let contract_signer = &get_vesting_account_signer_internal(vesting_contract); - move_to(contract_signer, - VestingAccountManagement { roles: simple_map::create(), }) + move_to( + contract_signer, + VestingAccountManagement { + roles: simple_map::create() + } + ) }; - let roles = &mut borrow_global_mut(contract_address).roles; + let roles = + &mut borrow_global_mut(contract_address).roles; simple_map::upsert(roles, role, role_holder); } public entry fun set_beneficiary_resetter( - admin: &signer, contract_address: address, beneficiary_resetter: address, + admin: &signer, + contract_address: address, + beneficiary_resetter: address ) acquires VestingAccountManagement, VestingContract { - set_management_role(admin, contract_address, utf8(ROLE_BENEFICIARY_RESETTER), - beneficiary_resetter); + set_management_role( + admin, + contract_address, + utf8(ROLE_BENEFICIARY_RESETTER), + beneficiary_resetter + ); } - public fun get_role_holder(contract_address: address, role: String): address acquires VestingAccountManagement { - assert!(exists(contract_address), - error::not_found(EVESTING_ACCOUNT_HAS_NO_ROLES)); + public fun get_role_holder( + contract_address: address, role: String + ): address acquires VestingAccountManagement { + assert!( + exists(contract_address), + error::not_found(EVESTING_ACCOUNT_HAS_NO_ROLES) + ); let roles = &borrow_global(contract_address).roles; assert!(simple_map::contains_key(roles, &role), error::not_found(EROLE_NOT_FOUND)); *simple_map::borrow(roles, &role) } /// For emergency use in case the admin needs emergency control of vesting contract account. - public fun get_vesting_account_signer(admin: &signer, contract_address: address): signer acquires VestingContract { + public fun get_vesting_account_signer( + admin: &signer, contract_address: address + ): signer acquires VestingContract { let vesting_contract = borrow_global_mut(contract_address); verify_admin(admin, vesting_contract); get_vesting_account_signer_internal(vesting_contract) } - fun get_vesting_account_signer_internal(vesting_contract: &VestingContract): signer { + fun get_vesting_account_signer_internal( + vesting_contract: &VestingContract + ): signer { account::create_signer_with_capability(&vesting_contract.signer_cap) } /// Create a salt for generating the resource accounts that will be holding the VestingContract. /// This address should be deterministic for the same admin and vesting contract creation nonce. - fun create_vesting_contract_account(admin: &signer, contract_creation_seed: vector,) - : (signer, SignerCapability) acquires AdminStore { + fun create_vesting_contract_account( + admin: &signer, contract_creation_seed: vector + ): (signer, SignerCapability) acquires AdminStore { let admin_store = borrow_global_mut(signer::address_of(admin)); let seed = bcs::to_bytes(&signer::address_of(admin)); vector::append(&mut seed, bcs::to_bytes(&admin_store.nonce)); @@ -736,43 +853,58 @@ module supra_framework::vesting_without_staking { } fun verify_admin(admin: &signer, vesting_contract: &VestingContract) { - assert!(signer::address_of(admin) == vesting_contract.admin, - error::unauthenticated(ENOT_ADMIN)); + assert!( + signer::address_of(admin) == vesting_contract.admin, + error::unauthenticated(ENOT_ADMIN) + ); } fun assert_vesting_contract_exists(contract_address: address) { - assert!(exists(contract_address), - error::not_found(EVESTING_CONTRACT_NOT_FOUND)); + assert!( + exists(contract_address), + error::not_found(EVESTING_CONTRACT_NOT_FOUND) + ); } - fun assert_shareholder_exists(contract_address: address, shareholder_address: address) acquires VestingContract { + fun assert_shareholder_exists( + contract_address: address, shareholder_address: address + ) acquires VestingContract { assert_active_vesting_contract(contract_address); - assert!(simple_map::contains_key(&borrow_global(contract_address) - .shareholders, &shareholder_address), - error::not_found(ESHAREHOLDER_NOT_EXIST)); + assert!( + simple_map::contains_key( + &borrow_global(contract_address).shareholders, + &shareholder_address + ), + error::not_found(ESHAREHOLDER_NOT_EXIST) + ); } fun assert_active_vesting_contract(contract_address: address) acquires VestingContract { assert_vesting_contract_exists(contract_address); let vesting_contract = borrow_global(contract_address); - assert!(vesting_contract.state == VESTING_POOL_ACTIVE, - error::invalid_state(EVESTING_CONTRACT_NOT_ACTIVE)); + assert!( + vesting_contract.state == VESTING_POOL_ACTIVE, + error::invalid_state(EVESTING_CONTRACT_NOT_ACTIVE) + ); } fun get_beneficiary(contract: &VestingContract, shareholder: address): address { if (simple_map::contains_key(&contract.beneficiaries, &shareholder)) { *simple_map::borrow(&contract.beneficiaries, &shareholder) - } else { shareholder } + } else { + shareholder + } } fun set_terminate_vesting_contract(contract_address: address) acquires VestingContract { let vesting_contract = borrow_global_mut(contract_address); vesting_contract.state = VESTING_POOL_TERMINATED; - emit_event(&mut vesting_contract.terminate_events, + emit_event( + &mut vesting_contract.terminate_events, TerminateEvent { admin: vesting_contract.admin, - vesting_contract_address: contract_address, - }, + vesting_contract_address: contract_address + } ); } @@ -792,17 +924,21 @@ module supra_framework::vesting_without_staking { const VESTING_PERIOD: u64 = 2592000; // 30 days #[test_only] - public entry fun setup(supra_framework: &signer, accounts: vector
) { + public entry fun setup( + supra_framework: &signer, accounts: vector
+ ) { use supra_framework::supra_account::create_account; timestamp::set_time_has_started_for_testing(supra_framework); stake::initialize_for_test(supra_framework); - vector::for_each_ref(&accounts, + vector::for_each_ref( + &accounts, |addr| { let addr: address = *addr; if (!account::exists_at(addr)) { create_account(addr); }; - }); + } + ); } #[test_only] @@ -810,10 +946,16 @@ module supra_framework::vesting_without_staking { admin: &signer, shareholders: &vector
, shares: &vector, - withdrawal_address: address, + withdrawal_address: address ): address acquires AdminStore { - setup_vesting_contract_with_schedule(admin, shareholders, shares, withdrawal_address, &vector[ - 2, 2, 1], 10,) + setup_vesting_contract_with_schedule( + admin, + shareholders, + shares, + withdrawal_address, + &vector[2, 2, 1], + 10 + ) } #[test_only] @@ -823,25 +965,37 @@ module supra_framework::vesting_without_staking { shares: &vector, withdrawal_address: address, vesting_numerators: &vector, - vesting_denominator: u64, + vesting_denominator: u64 ): address acquires AdminStore { let schedule = vector::empty(); - vector::for_each_ref(vesting_numerators, + vector::for_each_ref( + vesting_numerators, |num| { - vector::push_back(&mut schedule, - fixed_point32::create_from_rational(*num, vesting_denominator)); - }); - let vesting_schedule = create_vesting_schedule(schedule, timestamp::now_seconds() - + VESTING_SCHEDULE_CLIFF, VESTING_PERIOD,); + vector::push_back( + &mut schedule, + fixed_point32::create_from_rational(*num, vesting_denominator) + ); + } + ); + let vesting_schedule = + create_vesting_schedule( + schedule, + timestamp::now_seconds() + VESTING_SCHEDULE_CLIFF, + VESTING_PERIOD + ); let buy_ins = simple_map::create>(); - vector::enumerate_ref(shares, + vector::enumerate_ref( + shares, |i, share| { let shareholder = *vector::borrow(shareholders, i); simple_map::add(&mut buy_ins, shareholder, stake::mint_coins(*share)); - }); + } + ); - create_vesting_contract(admin, buy_ins, vesting_schedule, withdrawal_address, vector[],) + create_vesting_contract( + admin, buy_ins, vesting_schedule, withdrawal_address, vector[] + ) } #[test_only] @@ -852,22 +1006,42 @@ module supra_framework::vesting_without_staking { withdrawal_address: address, vesting_numerators: vector, vesting_denominator: u64 - ):address acquires AdminStore { - create_vesting_contract_with_amounts(admin, shareholders, shares, vesting_numerators, vesting_denominator, timestamp::now_seconds()+ VESTING_SCHEDULE_CLIFF, VESTING_PERIOD, withdrawal_address, vector[]); + ): address acquires AdminStore { + create_vesting_contract_with_amounts( + admin, + shareholders, + shares, + vesting_numerators, + vesting_denominator, + timestamp::now_seconds() + VESTING_SCHEDULE_CLIFF, + VESTING_PERIOD, + withdrawal_address, + vector[] + ); let admin_store = borrow_global(signer::address_of(admin)); - let contract_address = vector::borrow(&admin_store.vesting_contracts, vector::length(&admin_store.vesting_contracts) - 1); + let contract_address = vector::borrow( + &admin_store.vesting_contracts, + vector::length(&admin_store.vesting_contracts) - 1 + ); *contract_address } - - #[test(supra_framework = @0x1, admin = @0x123, shareholder_1 = @0x234, shareholder_2 = @0x345, withdrawal = @111)] + #[ + test( + supra_framework = @0x1, + admin = @0x123, + shareholder_1 = @0x234, + shareholder_2 = @0x345, + withdrawal = @111 + ) + ] #[expected_failure(abort_code = 0x30008, location = Self)] public entry fun test_termination_after_successful_vesting( supra_framework: &signer, admin: &signer, shareholder_1: &signer, shareholder_2: &signer, - withdrawal: &signer, + withdrawal: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let withdrawal_address = signer::address_of(withdrawal); @@ -878,16 +1052,24 @@ module supra_framework::vesting_without_staking { let shareholder_2_share = GRANT_AMOUNT * 3 / 4; let shares = &vector[shareholder_1_share, shareholder_2_share]; // Create the vesting contract. - setup(supra_framework, + setup( + supra_framework, vector[ admin_address, withdrawal_address, shareholder_1_address, - shareholder_2_address]); - let contract_address = setup_vesting_contract_with_schedule(admin, shareholders, - shares, withdrawal_address, &vector[1], 1,); - assert!(vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, 0); + shareholder_2_address + ] + ); + let contract_address = + setup_vesting_contract_with_schedule( + admin, shareholders, shares, withdrawal_address, &vector[1], 1 + ); + assert!( + vector::length(&borrow_global(admin_address).vesting_contracts) + == 1, + 0 + ); let vested_amount_1 = 0; let vested_amount_2 = 0; @@ -896,9 +1078,10 @@ module supra_framework::vesting_without_staking { assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); // Time is now at the start time, vest will unlock the first period, which is 2/10. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - )); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) + ); vest(contract_address); assert!(coin::balance(shareholder_1_address) == shareholder_1_share, 0); @@ -906,14 +1089,22 @@ module supra_framework::vesting_without_staking { vest(contract_address); } - #[test(supra_framework = @0x1, admin = @0x123, shareholder_1 = @0x234, shareholder_2 = @0x345, withdrawal = @111)] + #[ + test( + supra_framework = @0x1, + admin = @0x123, + shareholder_1 = @0x234, + shareholder_2 = @0x345, + withdrawal = @111 + ) + ] #[expected_failure(abort_code = 0x30008, location = Self)] public entry fun entry_test_termination_after_successful_vesting( supra_framework: &signer, admin: &signer, shareholder_1: &signer, shareholder_2: &signer, - withdrawal: &signer, + withdrawal: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let withdrawal_address = signer::address_of(withdrawal); @@ -924,28 +1115,36 @@ module supra_framework::vesting_without_staking { let shareholder_2_share = GRANT_AMOUNT * 3 / 4; let shares = vector[shareholder_1_share, shareholder_2_share]; // Create the vesting contract. - setup(supra_framework, + setup( + supra_framework, vector[ admin_address, withdrawal_address, shareholder_1_address, - shareholder_2_address]); + shareholder_2_address + ] + ); stake::mint(admin, GRANT_AMOUNT); - let contract_address = setup_vesting_contract_with_amount_with_schedule(admin, shareholders, - shares, withdrawal_address, vector[1], 1); - assert!(vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, 0); + let contract_address = + setup_vesting_contract_with_amount_with_schedule( + admin, shareholders, shares, withdrawal_address, vector[1], 1 + ); + assert!( + vector::length(&borrow_global(admin_address).vesting_contracts) + == 1, + 0 + ); let vested_amount_1 = 0; let vested_amount_2 = 0; assert!(coin::balance(contract_address) == GRANT_AMOUNT, 0); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); - // Time is now at the start time, vest will unlock the first period, which is 2/10. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - )); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) + ); vest(contract_address); assert!(coin::balance(shareholder_1_address) == shareholder_1_share, 0); @@ -953,13 +1152,21 @@ module supra_framework::vesting_without_staking { vest(contract_address); } - #[test(supra_framework = @0x1, admin = @0x123, shareholder_1 = @0x234, shareholder_2 = @0x345, withdrawal = @111)] + #[ + test( + supra_framework = @0x1, + admin = @0x123, + shareholder_1 = @0x234, + shareholder_2 = @0x345, + withdrawal = @111 + ) + ] public entry fun test_premature_call( supra_framework: &signer, admin: &signer, shareholder_1: &signer, shareholder_2: &signer, - withdrawal: &signer, + withdrawal: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let withdrawal_address = signer::address_of(withdrawal); @@ -970,16 +1177,24 @@ module supra_framework::vesting_without_staking { let shareholder_2_share = GRANT_AMOUNT * 3 / 4; let shares = &vector[shareholder_1_share, shareholder_2_share]; // Create the vesting contract. - setup(supra_framework, + setup( + supra_framework, vector[ admin_address, withdrawal_address, shareholder_1_address, - shareholder_2_address]); - let contract_address = setup_vesting_contract(admin, shareholders, shares, - withdrawal_address); - assert!(vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, 0); + shareholder_2_address + ] + ); + let contract_address = + setup_vesting_contract( + admin, shareholders, shares, withdrawal_address + ); + assert!( + vector::length(&borrow_global(admin_address).vesting_contracts) + == 1, + 0 + ); let vested_amount_1 = 0; let vested_amount_2 = 0; // Because the time is behind the start time, vest will do nothing. @@ -995,13 +1210,21 @@ module supra_framework::vesting_without_staking { assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); } - #[test(supra_framework = @0x1, admin = @0x123, shareholder_1 = @0x234, shareholder_2 = @0x345, withdrawal = @111)] + #[ + test( + supra_framework = @0x1, + admin = @0x123, + shareholder_1 = @0x234, + shareholder_2 = @0x345, + withdrawal = @111 + ) + ] public entry fun test_vest_individual( supra_framework: &signer, admin: &signer, shareholder_1: &signer, shareholder_2: &signer, - withdrawal: &signer, + withdrawal: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let withdrawal_address = signer::address_of(withdrawal); @@ -1012,80 +1235,123 @@ module supra_framework::vesting_without_staking { let shareholder_2_share = GRANT_AMOUNT * 3 / 4; let shares = &vector[shareholder_1_share, shareholder_2_share]; // Create the vesting contract. - setup(supra_framework, + setup( + supra_framework, vector[ admin_address, withdrawal_address, shareholder_1_address, - shareholder_2_address]); - let contract_address = setup_vesting_contract(admin, shareholders, shares, - withdrawal_address); - assert!(vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, 0); + shareholder_2_address + ] + ); + let contract_address = + setup_vesting_contract( + admin, shareholders, shares, withdrawal_address + ); + assert!( + vector::length(&borrow_global(admin_address).vesting_contracts) + == 1, + 0 + ); let vested_amount_1 = 0; let vested_amount_2 = 0; // Time is now at the start time, vest will unlock the first period, which is 2/10. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - )); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) + ); vest_individual(contract_address, shareholder_1_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 2, 10); - assert!(simple_map::borrow(&borrow_global(contract_address).shareholders, &shareholder_1_address) - .left_amount + vested_amount_1 == shareholder_1_share, - 0); + assert!( + simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_1_address + ).left_amount + vested_amount_1 == shareholder_1_share, + 0 + ); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); vest_individual(contract_address, shareholder_2_address); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 2, 10); - assert!(simple_map::borrow(&borrow_global(contract_address).shareholders, &shareholder_2_address) - .left_amount + vested_amount_2 == shareholder_2_share, - 0); + assert!( + simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_2_address + ).left_amount + vested_amount_2 == shareholder_2_share, + 0 + ); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 2); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 2 + ); vest_individual(contract_address, shareholder_1_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 2, 10); - assert!(simple_map::borrow(&borrow_global(contract_address).shareholders, &shareholder_1_address) - .left_amount + vested_amount_1 == shareholder_1_share, - 0); + assert!( + simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_1_address + ).left_amount + vested_amount_1 == shareholder_1_share, + 0 + ); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); vest_individual(contract_address, shareholder_2_address); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 2, 10); - assert!(simple_map::borrow(&borrow_global(contract_address).shareholders, &shareholder_2_address) - .left_amount + vested_amount_2 == shareholder_2_share, - 0); + assert!( + simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_2_address + ).left_amount + vested_amount_2 == shareholder_2_share, + 0 + ); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 3); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 3 + ); vest_individual(contract_address, shareholder_1_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); - assert!(simple_map::borrow(&borrow_global(contract_address).shareholders, &shareholder_1_address) - .left_amount + vested_amount_1 == shareholder_1_share, - 0); + assert!( + simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_1_address + ).left_amount + vested_amount_1 == shareholder_1_share, + 0 + ); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); vest_individual(contract_address, shareholder_2_address); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 1, 10); - assert!(simple_map::borrow(&borrow_global(contract_address).shareholders, &shareholder_2_address) - .left_amount + vested_amount_2 == shareholder_2_share, - 0); + assert!( + simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_2_address + ).left_amount + vested_amount_2 == shareholder_2_share, + 0 + ); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); } - #[test(supra_framework = @0x1, admin = @0x123, shareholder_1 = @0x234, shareholder_2 = @0x345, withdrawal = @111)] + #[ + test( + supra_framework = @0x1, + admin = @0x123, + shareholder_1 = @0x234, + shareholder_2 = @0x345, + withdrawal = @111 + ) + ] public entry fun test_vest_individual_early_termination_success( supra_framework: &signer, admin: &signer, shareholder_1: &signer, shareholder_2: &signer, - withdrawal: &signer, + withdrawal: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let withdrawal_address = signer::address_of(withdrawal); @@ -1096,56 +1362,89 @@ module supra_framework::vesting_without_staking { let shareholder_2_share = GRANT_AMOUNT * 3 / 4; let shares = &vector[shareholder_1_share, shareholder_2_share]; // Create the vesting contract. - setup(supra_framework, + setup( + supra_framework, vector[ admin_address, withdrawal_address, shareholder_1_address, - shareholder_2_address]); - let contract_address = setup_vesting_contract(admin, shareholders, shares, - withdrawal_address); - assert!(vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, 0); + shareholder_2_address + ] + ); + let contract_address = + setup_vesting_contract( + admin, shareholders, shares, withdrawal_address + ); + assert!( + vector::length(&borrow_global(admin_address).vesting_contracts) + == 1, + 0 + ); let vested_amount_1 = 0; let vested_amount_2 = 0; // Time is now at the start time, vest will unlock the first period, which is 2/10. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 50); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 50 + ); vest_individual(contract_address, shareholder_1_address); vested_amount_1 = vested_amount_1 + GRANT_AMOUNT / 4; - assert!(simple_map::borrow(&borrow_global(contract_address).shareholders, &shareholder_1_address) - .left_amount + vested_amount_1 == shareholder_1_share, - 0); + assert!( + simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_1_address + ).left_amount + vested_amount_1 == shareholder_1_share, + 0 + ); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); vest_individual(contract_address, shareholder_2_address); vested_amount_2 = vested_amount_2 + (GRANT_AMOUNT * 3 / 4); - assert!(simple_map::borrow(&borrow_global(contract_address).shareholders, &shareholder_2_address) - .left_amount + vested_amount_2 == shareholder_2_share, - 0); + assert!( + simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_2_address + ).left_amount + vested_amount_2 == shareholder_2_share, + 0 + ); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); - let vesting_record_1 = simple_map::borrow(&borrow_global( - contract_address - ).shareholders, &shareholder_1_address); - let vesting_record_2 = simple_map::borrow(&borrow_global( - contract_address - ).shareholders, &shareholder_2_address); + let vesting_record_1 = + simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_1_address + ); + let vesting_record_2 = + simple_map::borrow( + &borrow_global(contract_address).shareholders, + &shareholder_2_address + ); //Check that loop only as many vesting periods have passed which is required to vest everything - assert!(vesting_record_1.last_vested_period == 9, vesting_record_1.last_vested_period); - assert!(vesting_record_2.last_vested_period == 9, vesting_record_2.last_vested_period); + assert!( + vesting_record_1.last_vested_period == 9, vesting_record_1.last_vested_period + ); + assert!( + vesting_record_2.last_vested_period == 9, vesting_record_2.last_vested_period + ); } - #[test(supra_framework = @0x1, admin = @0x123, shareholder_1 = @0x234, shareholder_2 = @0x345, withdrawal = @111)] + #[ + test( + supra_framework = @0x1, + admin = @0x123, + shareholder_1 = @0x234, + shareholder_2 = @0x345, + withdrawal = @111 + ) + ] public entry fun test_end_to_end( supra_framework: &signer, admin: &signer, shareholder_1: &signer, shareholder_2: &signer, - withdrawal: &signer, + withdrawal: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let withdrawal_address = signer::address_of(withdrawal); @@ -1156,16 +1455,24 @@ module supra_framework::vesting_without_staking { let shareholder_2_share = GRANT_AMOUNT * 3 / 4; let shares = &vector[shareholder_1_share, shareholder_2_share]; // Create the vesting contract. - setup(supra_framework, + setup( + supra_framework, vector[ admin_address, withdrawal_address, shareholder_1_address, - shareholder_2_address]); - let contract_address = setup_vesting_contract(admin, shareholders, shares, - withdrawal_address); - assert!(vector::length(&borrow_global(admin_address).vesting_contracts) == - 1, 0); + shareholder_2_address + ] + ); + let contract_address = + setup_vesting_contract( + admin, shareholders, shares, withdrawal_address + ); + assert!( + vector::length(&borrow_global(admin_address).vesting_contracts) + == 1, + 0 + ); let vested_amount_1 = 0; let vested_amount_2 = 0; // Because the time is behind the start time, vest will do nothing. @@ -1175,81 +1482,90 @@ module supra_framework::vesting_without_staking { assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); // Time is now at the start time, vest will unlock the first period, which is 2/10. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - )); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) + ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 2, 10); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 2, 10); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 2); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 2 + ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 2, 10); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 2, 10); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 3); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 3 + ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 1, 10); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 4); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 4 + ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 1, 10); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 5); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 5 + ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 1, 10); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 6); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 6 + ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 1, 10); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 7); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 7 + ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 1, 10); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 8); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 8 + ); vest(contract_address); vested_amount_1 = vested_amount_1 + fraction(shareholder_1_share, 1, 10); vested_amount_2 = vested_amount_2 + fraction(shareholder_2_share, 1, 10); assert!(coin::balance(shareholder_1_address) == vested_amount_1, 0); assert!(coin::balance(shareholder_2_address) == vested_amount_2, 0); - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - ) * 9); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) * 9 + ); vest(contract_address); vested_amount_1 = shareholder_1_share; vested_amount_2 = shareholder_2_share; @@ -1260,7 +1576,7 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x1000C, location = Self)] public entry fun test_create_vesting_contract_with_zero_grant_should_fail( - supra_framework: &signer, admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); @@ -1270,7 +1586,7 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x10004, location = Self)] public entry fun test_create_vesting_contract_with_no_shareholders_should_fail( - supra_framework: &signer, admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); @@ -1280,7 +1596,7 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x60001, location = supra_framework::supra_account)] public entry fun test_create_vesting_contract_with_invalid_withdrawal_address_should_fail( - supra_framework: &signer, admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); @@ -1290,7 +1606,7 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x60001, location = supra_framework::supra_account)] public entry fun test_create_vesting_contract_with_missing_withdrawal_account_should_fail( - supra_framework: &signer, admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); @@ -1300,7 +1616,7 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x60002, location = supra_framework::supra_account)] public entry fun test_create_vesting_contract_with_unregistered_withdrawal_account_should_fail( - supra_framework: &signer, admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); @@ -1310,7 +1626,9 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1)] #[expected_failure(abort_code = 0x10002, location = Self)] - public entry fun test_create_empty_vesting_schedule_should_fail(supra_framework: &signer) { + public entry fun test_create_empty_vesting_schedule_should_fail( + supra_framework: &signer + ) { setup(supra_framework, vector[]); create_vesting_schedule(vector[], 1, 1); } @@ -1321,11 +1639,14 @@ module supra_framework::vesting_without_staking { supra_framework: &signer ) { setup(supra_framework, vector[]); - create_vesting_schedule(vector[ + create_vesting_schedule( + vector[ fixed_point32::create_from_raw_value(0), - fixed_point32::create_from_raw_value(8)], + fixed_point32::create_from_raw_value(8) + ], 1, - 1); + 1 + ); } #[test(supra_framework = @0x1)] @@ -1334,11 +1655,14 @@ module supra_framework::vesting_without_staking { supra_framework: &signer ) { setup(supra_framework, vector[]); - create_vesting_schedule(vector[ + create_vesting_schedule( + vector[ fixed_point32::create_from_raw_value(8), - fixed_point32::create_from_raw_value(0)], + fixed_point32::create_from_raw_value(0) + ], 1, - 1); + 1 + ); } #[test(supra_framework = @0x1)] @@ -1362,70 +1686,101 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1, admin = @0x123, shareholder = @0x234)] public entry fun test_last_vest_should_distribute_remaining_amount( - supra_framework: &signer, admin: &signer, shareholder: &signer, + supra_framework: &signer, + admin: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract_with_schedule(admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], - admin_address, - // First vest = 3/4 but last vest should only be for the remaining 1/4. - &vector[3], 4,); + let contract_address = + setup_vesting_contract_with_schedule( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address, + // First vest = 3/4 but last vest should only be for the remaining 1/4. + &vector[3], + 4 + ); // First vest is 3/4 - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + VESTING_PERIOD); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + VESTING_PERIOD + ); vest(contract_address); let vested_amount = fraction(GRANT_AMOUNT, 3, 4); let remaining_grant = GRANT_AMOUNT - vested_amount; - assert!(remaining_grant(contract_address, shareholder_address) == remaining_grant, - 0); + assert!( + remaining_grant(contract_address, shareholder_address) == remaining_grant, 0 + ); timestamp::fast_forward_seconds(VESTING_PERIOD); // Last vest should be the remaining amount (1/4). vest(contract_address); remaining_grant = 0; - assert!(remaining_grant(contract_address, shareholder_address) == remaining_grant, - 0); + assert!( + remaining_grant(contract_address, shareholder_address) == remaining_grant, 0 + ); } #[test(supra_framework = @0x1, admin = @0x123, shareholder = @0x234)] public entry fun entry_test_last_vest_should_distribute_remaining_amount( - supra_framework: &signer, admin: &signer, shareholder: &signer, + supra_framework: &signer, + admin: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, vector[admin_address, shareholder_address]); stake::mint(admin, GRANT_AMOUNT); - let contract_address = setup_vesting_contract_with_amount_with_schedule(admin, vector[shareholder_address], vector[GRANT_AMOUNT], - admin_address, - // First vest = 3/4 but last vest should only be for the remaining 1/4. - vector[3], 4,); + let contract_address = + setup_vesting_contract_with_amount_with_schedule( + admin, + vector[shareholder_address], + vector[GRANT_AMOUNT], + admin_address, + // First vest = 3/4 but last vest should only be for the remaining 1/4. + vector[3], + 4 + ); // First vest is 3/4 - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + VESTING_PERIOD); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + VESTING_PERIOD + ); vest(contract_address); let vested_amount = fraction(GRANT_AMOUNT, 3, 4); let remaining_grant = GRANT_AMOUNT - vested_amount; - assert!(remaining_grant(contract_address, shareholder_address) == remaining_grant, - 0); + assert!( + remaining_grant(contract_address, shareholder_address) == remaining_grant, 0 + ); timestamp::fast_forward_seconds(VESTING_PERIOD); // Last vest should be the remaining amount (1/4). vest(contract_address); remaining_grant = 0; - assert!(remaining_grant(contract_address, shareholder_address) == remaining_grant, - 0); + assert!( + remaining_grant(contract_address, shareholder_address) == remaining_grant, 0 + ); } #[test(supra_framework = @0x1, admin = @0x123, shareholder = @0x234)] #[expected_failure(abort_code = 0x30008, location = Self)] public entry fun test_cannot_vest_after_contract_is_terminated( - supra_framework: &signer, admin: &signer, shareholder: &signer, + supra_framework: &signer, + admin: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract(admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address + ); // Immediately terminate. Calling vest should now fail. terminate_vesting_contract(admin, contract_address); @@ -1435,13 +1790,20 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1, admin = @0x123, shareholder = @0x234)] #[expected_failure(abort_code = 0x30008, location = Self)] public entry fun test_cannot_terminate_twice( - supra_framework: &signer, admin: &signer, shareholder: &signer, + supra_framework: &signer, + admin: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract(admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address + ); // Call terminate_vesting_contract twice should fail. terminate_vesting_contract(admin, contract_address); @@ -1451,13 +1813,20 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1, admin = @0x123, shareholder = @0x234)] #[expected_failure(abort_code = 0x30009, location = Self)] public entry fun test_cannot_call_admin_withdraw_if_contract_is_not_terminated( - supra_framework: &signer, admin: &signer, shareholder: &signer, + supra_framework: &signer, + admin: &signer, + shareholder: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); let shareholder_address = signer::address_of(shareholder); setup(supra_framework, vector[admin_address, shareholder_address]); - let contract_address = setup_vesting_contract(admin, &vector[shareholder_address], &vector[GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, + &vector[shareholder_address], + &vector[GRANT_AMOUNT], + admin_address + ); // Calling admin_withdraw should fail as contract has not been terminated. admin_withdraw(admin, contract_address); @@ -1466,41 +1835,55 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x60001, location = supra_framework::supra_account)] public entry fun test_set_beneficiary_with_missing_account_should_fail( - supra_framework: &signer, admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); - let contract_address = setup_vesting_contract(admin, &vector[@1, @2], &vector[GRANT_AMOUNT, GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, + &vector[@1, @2], + &vector[GRANT_AMOUNT, GRANT_AMOUNT], + admin_address + ); set_beneficiary(admin, contract_address, @1, @11); } #[test(supra_framework = @0x1, admin = @0x123)] #[expected_failure(abort_code = 0x60002, location = supra_framework::supra_account)] public entry fun test_set_beneficiary_with_unregistered_account_should_fail( - supra_framework: &signer, admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); - let contract_address = setup_vesting_contract(admin, &vector[@1, @2], &vector[GRANT_AMOUNT, GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, + &vector[@1, @2], + &vector[GRANT_AMOUNT, GRANT_AMOUNT], + admin_address + ); create_account_for_test(@11); set_beneficiary(admin, contract_address, @1, @11); } #[test(supra_framework = @0x1, admin = @0x123)] public entry fun test_set_beneficiary_should_send_distribution( - supra_framework: &signer, admin: &signer, + supra_framework: &signer, admin: &signer ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address, @11]); - let contract_address = setup_vesting_contract(admin, &vector[@1], &vector[GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, &vector[@1], &vector[GRANT_AMOUNT], admin_address + ); set_beneficiary(admin, contract_address, @1, @11); assert!(beneficiary(contract_address, @1) == @11, 0); // Fast forward to the end of the first period. vest() should now unlock 2/10 of the tokens. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + VESTING_PERIOD); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + VESTING_PERIOD + ); vest(contract_address); let vested_amount = fraction(GRANT_AMOUNT, 2, 10); @@ -1509,11 +1892,15 @@ module supra_framework::vesting_without_staking { } #[test(supra_framework = @0x1, admin = @0x123)] - public entry fun test_set_management_role(supra_framework: &signer, admin: &signer,) acquires AdminStore, VestingAccountManagement, VestingContract { + public entry fun test_set_management_role( + supra_framework: &signer, admin: &signer + ) acquires AdminStore, VestingAccountManagement, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address]); - let contract_address = setup_vesting_contract(admin, &vector[@11], &vector[GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address + ); let role = utf8(b"RANDOM"); set_management_role(admin, contract_address, role, @12); assert!(get_role_holder(contract_address, role) == @12, 0); @@ -1522,18 +1909,23 @@ module supra_framework::vesting_without_staking { } #[test(supra_framework = @0x1, admin = @0x123)] - public entry fun test_reset_beneficiary(supra_framework: &signer, admin: &signer,) acquires AdminStore, VestingAccountManagement, VestingContract { + public entry fun test_reset_beneficiary( + supra_framework: &signer, admin: &signer + ) acquires AdminStore, VestingAccountManagement, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address, @11, @12]); - let contract_address = setup_vesting_contract(admin, &vector[@11], &vector[GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address + ); set_beneficiary(admin, contract_address, @11, @12); assert!(beneficiary(contract_address, @11) == @12, 0); // Fast forward to the end of the first period. vest() should now unlock 2/10 of the tokens. - timestamp::update_global_time_for_test_secs(vesting_start_secs(contract_address) + period_duration_secs( - contract_address - )); + timestamp::update_global_time_for_test_secs( + vesting_start_secs(contract_address) + + period_duration_secs(contract_address) + ); vest(contract_address); // Reset the beneficiary. @@ -1546,37 +1938,48 @@ module supra_framework::vesting_without_staking { #[test(supra_framework = @0x1, admin = @0x123, resetter = @0x234)] public entry fun test_reset_beneficiary_with_resetter_role( - supra_framework: &signer, admin: &signer, resetter: &signer, + supra_framework: &signer, + admin: &signer, + resetter: &signer ) acquires AdminStore, VestingAccountManagement, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address, @11, @12]); - let contract_address = setup_vesting_contract(admin, &vector[@11], &vector[GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address + ); set_beneficiary(admin, contract_address, @11, @12); assert!(beneficiary(contract_address, @11) == @12, 0); // Reset the beneficiary with the resetter role. let resetter_address = signer::address_of(resetter); set_beneficiary_resetter(admin, contract_address, resetter_address); - assert!(simple_map::length(&borrow_global( - contract_address - ).roles) == 1, 0); + assert!( + simple_map::length( + &borrow_global(contract_address).roles + ) == 1, + 0 + ); reset_beneficiary(resetter, contract_address, @11); assert!(beneficiary(contract_address, @11) == @11, 0); } - #[test(supra_framework = @0x1, admin = @0x123, resetter = @0x234, random = @0x345)] + #[test( + supra_framework = @0x1, admin = @0x123, resetter = @0x234, random = @0x345 + )] #[expected_failure(abort_code = 0x5000F, location = Self)] public entry fun test_reset_beneficiary_with_unauthorized( supra_framework: &signer, admin: &signer, resetter: &signer, - random: &signer, + random: &signer ) acquires AdminStore, VestingAccountManagement, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address, @11]); - let contract_address = setup_vesting_contract(admin, &vector[@11], &vector[GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address + ); // Reset the beneficiary with a random account. This should failed. set_beneficiary_resetter(admin, contract_address, signer::address_of(resetter)); @@ -1584,11 +1987,15 @@ module supra_framework::vesting_without_staking { } #[test(supra_framework = @0x1, admin = @0x123)] - public entry fun test_shareholder(supra_framework: &signer, admin: &signer,) acquires AdminStore, VestingContract { + public entry fun test_shareholder( + supra_framework: &signer, admin: &signer + ) acquires AdminStore, VestingContract { let admin_address = signer::address_of(admin); setup(supra_framework, vector[admin_address, @11, @12]); - let contract_address = setup_vesting_contract(admin, &vector[@11], &vector[GRANT_AMOUNT], - admin_address); + let contract_address = + setup_vesting_contract( + admin, &vector[@11], &vector[GRANT_AMOUNT], admin_address + ); // Confirm that the lookup returns the same address when a shareholder is // passed for which there is no beneficiary. @@ -1613,7 +2020,8 @@ module supra_framework::vesting_without_staking { #[test_only] fun fraction(total: u64, numerator: u64, denominator: u64): u64 { - fixed_point32::multiply_u64(total, - fixed_point32::create_from_rational(numerator, denominator)) + fixed_point32::multiply_u64( + total, fixed_point32::create_from_rational(numerator, denominator) + ) } } diff --git a/aptos-move/framework/supra-framework/sources/vesting_without_staking.spec.move b/aptos-move/framework/supra-framework/sources/vesting_without_staking.spec.move index 3dd2c83d54f8c..7e093327dacaf 100644 --- a/aptos-move/framework/supra-framework/sources/vesting_without_staking.spec.move +++ b/aptos-move/framework/supra-framework/sources/vesting_without_staking.spec.move @@ -10,41 +10,51 @@ spec supra_framework::vesting_without_staking { spec vesting_start_secs { pragma verify = true; - include VestingContractExists{contract_address: vesting_contract_address}; + include VestingContractExists { contract_address: vesting_contract_address }; } spec period_duration_secs { pragma verify = true; - include VestingContractExists{contract_address: vesting_contract_address}; + include VestingContractExists { contract_address: vesting_contract_address }; } spec remaining_grant { pragma verify = true; - include VestingContractExists{contract_address: vesting_contract_address}; - aborts_if !simple_map::spec_contains_key(global(vesting_contract_address).shareholders, shareholder_address); + include VestingContractExists { contract_address: vesting_contract_address }; + aborts_if !simple_map::spec_contains_key( + global(vesting_contract_address).shareholders, + shareholder_address + ); // ensure that the remaining grant is equal to the left amount of the shareholder - ensures result == simple_map::spec_get(global(vesting_contract_address).shareholders, shareholder_address).left_amount; + ensures result + == simple_map::spec_get( + global(vesting_contract_address).shareholders, + shareholder_address + ).left_amount; } spec beneficiary { pragma verify = true; - include VestingContractExists{contract_address: vesting_contract_address}; + include VestingContractExists { contract_address: vesting_contract_address }; } spec vesting_contracts { pragma verify = true; aborts_if false; // ensure that an empty vector is returned if the admin doesn't exist - ensures !exists(admin) ==> result == vector::empty
(); + ensures !exists(admin) ==> + result == vector::empty
(); // ensure that the vesting contracts are returned if the admin exists - ensures exists(admin) ==> result == global(admin).vesting_contracts; + ensures exists(admin) ==> + result == global(admin).vesting_contracts; } spec vesting_schedule { pragma verify = true; - include VestingContractExists{contract_address: vesting_contract_address}; + include VestingContractExists { contract_address: vesting_contract_address }; // ensure that the vesting schedule is returned if the vesting contract exists - ensures result == global(vesting_contract_address).vesting_schedule; + ensures result + == global(vesting_contract_address).vesting_schedule; } // spec shareholders { @@ -79,12 +89,16 @@ spec supra_framework::vesting_without_staking { let vesting_schedule = vesting_contract_pre.vesting_schedule; let last_vested_period = vesting_schedule.last_vested_period; let next_period_to_vest = last_vested_period + 1; - let last_completed_period = - (timestamp::spec_now_seconds() - vesting_schedule.start_timestamp_secs) / vesting_schedule.period_duration; + let last_completed_period = ( + timestamp::spec_now_seconds() - vesting_schedule.start_timestamp_secs + ) / vesting_schedule.period_duration; // ensure the vesting contract is the same if the vesting period is not reached - ensures vesting_contract_pre.vesting_schedule.start_timestamp_secs > timestamp::spec_now_seconds() ==> vesting_contract_pre == vesting_contract_post; + ensures vesting_contract_pre.vesting_schedule.start_timestamp_secs + > timestamp::spec_now_seconds() ==> + vesting_contract_pre == vesting_contract_post; // ensure the vesting contract is the same if the last completed period is greater than the next period to vest - ensures last_completed_period < next_period_to_vest ==> vesting_contract_pre == vesting_contract_post; + ensures last_completed_period < next_period_to_vest ==> + vesting_contract_pre == vesting_contract_post; } spec vest_individual { @@ -101,21 +115,30 @@ spec supra_framework::vesting_without_staking { // (timestamp::spec_now_seconds() - vesting_schedule.start_timestamp_secs) / vesting_schedule.period_duration; // let post post_balance = coin::balance(contract_address); // ensure the vesting contract is the same if the vesting period is not reached - ensures vesting_contract_pre.vesting_schedule.start_timestamp_secs > timestamp::spec_now_seconds() ==> vesting_contract_pre == vesting_contract_post; + ensures vesting_contract_pre.vesting_schedule.start_timestamp_secs + > timestamp::spec_now_seconds() ==> + vesting_contract_pre == vesting_contract_post; // ensure the vesting contract is the same if the last completed period is greater than the next period to vest // ensures (last_completed_period < next_period_to_vest && post_balance > 0) ==> vesting_contract_pre == vesting_contract_post; } spec vest_transfer { pragma verify = true; - let amount = min(vesting_record.left_amount, fixed_point32::spec_multiply_u64(vesting_record.init_amount, vesting_fraction)); + let amount = min( + vesting_record.left_amount, + fixed_point32::spec_multiply_u64(vesting_record.init_amount, vesting_fraction) + ); // Ensure that the amount is substracted from the left_amount ensures vesting_record.left_amount == old(vesting_record.left_amount) - amount; let address_from = signer_cap.account; // Ensure that the amount is transferred from the address_from to the beneficiary ensures beneficiary != address_from ==> - (coin::balance(beneficiary) == old(coin::balance(beneficiary)) + amount - && coin::balance(address_from) == old(coin::balance(address_from)) - amount); + ( + coin::balance(beneficiary) + == old(coin::balance(beneficiary)) + amount + && coin::balance(address_from) + == old(coin::balance(address_from)) - amount + ); } spec remove_shareholder { @@ -125,14 +148,24 @@ spec supra_framework::vesting_without_staking { let vesting_contract = global(contract_address); let post vesting_contract_post = global(contract_address); let balance_pre = coin::balance(vesting_contract.withdrawal_address); - let post balance_post = coin::balance(vesting_contract_post.withdrawal_address); - let shareholder_amount = simple_map::spec_get(vesting_contract.shareholders, shareholder_address).left_amount; + let post balance_post = coin::balance( + vesting_contract_post.withdrawal_address + ); + let shareholder_amount = simple_map::spec_get( + vesting_contract.shareholders, shareholder_address + ).left_amount; // ensure that `withdrawal address` receives the `shareholder_amount` - ensures vesting_contract_post.withdrawal_address != vesting_contract.signer_cap.account ==> balance_post == balance_pre + shareholder_amount; + ensures vesting_contract_post.withdrawal_address + != vesting_contract.signer_cap.account ==> + balance_post == balance_pre + shareholder_amount; // ensure that `shareholder_address` is indeed removed from the contract - ensures !simple_map::spec_contains_key(vesting_contract_post.shareholders, shareholder_address); + ensures !simple_map::spec_contains_key( + vesting_contract_post.shareholders, shareholder_address + ); // ensure that beneficiary doesn't exist for the corresponding shareholder - ensures !simple_map::spec_contains_key(vesting_contract_post.beneficiaries, shareholder_address); + ensures !simple_map::spec_contains_key( + vesting_contract_post.beneficiaries, shareholder_address + ); } // spec terminate_vesting_contract { @@ -146,9 +179,13 @@ spec supra_framework::vesting_without_staking { pragma aborts_if_is_partial = true; let vesting_contract = global(contract_address); let balance_pre = coin::balance(vesting_contract.withdrawal_address); - let post balance_post = coin::balance(vesting_contract.withdrawal_address); + let post balance_post = coin::balance( + vesting_contract.withdrawal_address + ); let post balance_contract = coin::balance(contract_address); - aborts_if !(global(contract_address).state == VESTING_POOL_TERMINATED); + aborts_if !( + global(contract_address).state == VESTING_POOL_TERMINATED + ); // // ensure that the `withdrawal_address` receives the remaining balance // ensures (vesting_contract.signer_cap.account != vesting_contract.withdrawal_address) ==> balance_post == balance_pre + coin::balance(contract_address); // // ensure that the contract balance is 0 @@ -160,16 +197,19 @@ spec supra_framework::vesting_without_staking { pragma aborts_if_is_partial = true; let vesting_contract_pre = global(contract_address); let post vesting_contract_post = global(contract_address); - include AdminAborts{vesting_contract: vesting_contract_pre}; + include AdminAborts { vesting_contract: vesting_contract_pre }; // ensure that the beneficiary is set to the new_beneficiary - ensures simple_map::spec_get(vesting_contract_post.beneficiaries, shareholder) == new_beneficiary; + ensures simple_map::spec_get(vesting_contract_post.beneficiaries, shareholder) + == new_beneficiary; } spec reset_beneficiary { pragma verify = true; let post vesting_contract = global(contract_address); // ensure that the beneficiary is removed for the shareholder - ensures !simple_map::spec_contains_key(vesting_contract.beneficiaries, shareholder); + ensures !simple_map::spec_contains_key( + vesting_contract.beneficiaries, shareholder + ); } spec set_management_role { @@ -209,6 +249,7 @@ spec supra_framework::vesting_without_staking { pragma verify = true; include AdminAborts; } + spec schema AdminAborts { admin: &signer; vesting_contract: &VestingContract; @@ -242,9 +283,11 @@ spec supra_framework::vesting_without_staking { pragma opaque; aborts_if false; // ensure that the beneficiary is returned if it exists, note this is used in distribute_to_shareholder function - ensures simple_map::spec_contains_key(contract.beneficiaries, shareholder) ==> result == simple_map::spec_get(contract.beneficiaries, shareholder); + ensures simple_map::spec_contains_key(contract.beneficiaries, shareholder) ==> + result == simple_map::spec_get(contract.beneficiaries, shareholder); // ensure that the shareholder is returned if the beneficiary doesn't exist, note this is used in distribute_to_shareholder function - ensures !simple_map::spec_contains_key(contract.beneficiaries, shareholder) ==> result == shareholder; + ensures !simple_map::spec_contains_key(contract.beneficiaries, shareholder) ==> + result == shareholder; } spec set_terminate_vesting_contract { diff --git a/aptos-move/framework/supra-framework/sources/voting.move b/aptos-move/framework/supra-framework/sources/voting.move index 27e8a46cb88ef..c0a75eb0c5369 100644 --- a/aptos-move/framework/supra-framework/sources/voting.move +++ b/aptos-move/framework/supra-framework/sources/voting.move @@ -120,7 +120,7 @@ module supra_framework::voting { /// Whether the proposal has been resolved. is_resolved: bool, /// Resolution timestamp if the proposal has been resolved. 0 otherwise. - resolution_time_secs: u64, + resolution_time_secs: u64 } struct VotingForum has key { @@ -129,14 +129,14 @@ module supra_framework::voting { proposals: Table>, events: VotingEvents, /// Unique identifier for a proposal. This allows for 2 * 10**19 proposals. - next_proposal_id: u64, + next_proposal_id: u64 } struct VotingEvents has store { create_proposal_events: EventHandle, register_forum_events: EventHandle, resolve_proposal_events: EventHandle, - vote_events: EventHandle, + vote_events: EventHandle } #[event] @@ -146,19 +146,19 @@ module supra_framework::voting { execution_hash: vector, expiration_secs: u64, metadata: SimpleMap>, - min_vote_threshold: u128, + min_vote_threshold: u128 } #[event] struct RegisterForum has drop, store { hosting_account: address, - proposal_type_info: TypeInfo, + proposal_type_info: TypeInfo } #[event] struct Vote has drop, store { proposal_id: u64, - num_votes: u64, + num_votes: u64 } #[event] @@ -175,31 +175,40 @@ module supra_framework::voting { execution_hash: vector, expiration_secs: u64, metadata: SimpleMap>, - min_vote_threshold: u128, + min_vote_threshold: u128 } struct RegisterForumEvent has drop, store { hosting_account: address, - proposal_type_info: TypeInfo, + proposal_type_info: TypeInfo } struct VoteEvent has drop, store { proposal_id: u64, - num_votes: u64, + num_votes: u64 } public fun register(account: &signer) { let addr = signer::address_of(account); - assert!(!exists>(addr), error::already_exists(EVOTING_FORUM_ALREADY_REGISTERED)); + assert!( + !exists>(addr), + error::already_exists(EVOTING_FORUM_ALREADY_REGISTERED) + ); let voting_forum = VotingForum { next_proposal_id: 0, proposals: table::new>(), events: VotingEvents { - create_proposal_events: account::new_event_handle(account), - register_forum_events: account::new_event_handle(account), - resolve_proposal_events: account::new_event_handle(account), - vote_events: account::new_event_handle(account), + create_proposal_events: account::new_event_handle( + account + ), + register_forum_events: account::new_event_handle( + account + ), + resolve_proposal_events: account::new_event_handle( + account + ), + vote_events: account::new_event_handle(account) } }; @@ -207,16 +216,16 @@ module supra_framework::voting { event::emit( RegisterForum { hosting_account: addr, - proposal_type_info: type_info::type_of(), - }, + proposal_type_info: type_info::type_of() + } ); }; event::emit_event( &mut voting_forum.events.register_forum_events, RegisterForumEvent { hosting_account: addr, - proposal_type_info: type_info::type_of(), - }, + proposal_type_info: type_info::type_of() + } ); move_to(account, voting_forum); @@ -242,7 +251,7 @@ module supra_framework::voting { min_vote_threshold: u128, expiration_secs: u64, early_resolution_vote_threshold: Option, - metadata: SimpleMap>, + metadata: SimpleMap> ): u64 acquires VotingForum { create_proposal_v2( proposer, @@ -279,50 +288,67 @@ module supra_framework::voting { expiration_secs: u64, early_resolution_vote_threshold: Option, metadata: SimpleMap>, - is_multi_step_proposal: bool, + is_multi_step_proposal: bool ): u64 acquires VotingForum { if (option::is_some(&early_resolution_vote_threshold)) { assert!( min_vote_threshold <= *option::borrow(&early_resolution_vote_threshold), - error::invalid_argument(EINVALID_MIN_VOTE_THRESHOLD), + error::invalid_argument(EINVALID_MIN_VOTE_THRESHOLD) ); }; // Make sure the execution script's hash is not empty. - assert!(vector::length(&execution_hash) > 0, error::invalid_argument(EPROPOSAL_EMPTY_EXECUTION_HASH)); + assert!( + vector::length(&execution_hash) > 0, + error::invalid_argument(EPROPOSAL_EMPTY_EXECUTION_HASH) + ); - let voting_forum = borrow_global_mut>(voting_forum_address); + let voting_forum = + borrow_global_mut>(voting_forum_address); let proposal_id = voting_forum.next_proposal_id; voting_forum.next_proposal_id = voting_forum.next_proposal_id + 1; // Add a flag to indicate if this proposal is single-step or multi-step. - simple_map::add(&mut metadata, utf8(IS_MULTI_STEP_PROPOSAL_KEY), to_bytes(&is_multi_step_proposal)); + simple_map::add( + &mut metadata, + utf8(IS_MULTI_STEP_PROPOSAL_KEY), + to_bytes(&is_multi_step_proposal) + ); - let is_multi_step_in_execution_key = utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); + let is_multi_step_in_execution_key = + utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); if (is_multi_step_proposal) { // If the given proposal is a multi-step proposal, we will add a flag to indicate if this multi-step proposal is in execution. // This value is by default false. We turn this value to true when we start executing the multi-step proposal. This value // will be used to disable further voting after we started executing the multi-step proposal. - simple_map::add(&mut metadata, is_multi_step_in_execution_key, to_bytes(&false)); + simple_map::add( + &mut metadata, is_multi_step_in_execution_key, to_bytes(&false) + ); // If the proposal is a single-step proposal, we check if the metadata passed by the client has the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY key. // If they have the key, we will remove it, because a single-step proposal that doesn't need this key. - } else if (simple_map::contains_key(&mut metadata, &is_multi_step_in_execution_key)) { + } else if (simple_map::contains_key( + &mut metadata, &is_multi_step_in_execution_key + )) { simple_map::remove(&mut metadata, &is_multi_step_in_execution_key); }; - table::add(&mut voting_forum.proposals, proposal_id, Proposal { - proposer, - creation_time_secs: timestamp::now_seconds(), - execution_content: option::some(execution_content), - execution_hash, - metadata, - min_vote_threshold, - expiration_secs, - early_resolution_vote_threshold, - yes_votes: 0, - no_votes: 0, - is_resolved: false, - resolution_time_secs: 0, - }); + table::add( + &mut voting_forum.proposals, + proposal_id, + Proposal { + proposer, + creation_time_secs: timestamp::now_seconds(), + execution_content: option::some(execution_content), + execution_hash, + metadata, + min_vote_threshold, + expiration_secs, + early_resolution_vote_threshold, + yes_votes: 0, + no_votes: 0, + is_resolved: false, + resolution_time_secs: 0 + } + ); if (std::features::module_event_migration_enabled()) { event::emit( @@ -332,8 +358,8 @@ module supra_framework::voting { execution_hash, expiration_secs, metadata, - min_vote_threshold, - }, + min_vote_threshold + } ); }; event::emit_event( @@ -344,8 +370,8 @@ module supra_framework::voting { execution_hash, expiration_secs, metadata, - min_vote_threshold, - }, + min_vote_threshold + } ); proposal_id @@ -364,23 +390,30 @@ module supra_framework::voting { voting_forum_address: address, proposal_id: u64, num_votes: u64, - should_pass: bool, + should_pass: bool ) acquires VotingForum { - let voting_forum = borrow_global_mut>(voting_forum_address); + let voting_forum = + borrow_global_mut>(voting_forum_address); let proposal = table::borrow_mut(&mut voting_forum.proposals, proposal_id); // Voting might still be possible after the proposal has enough yes votes to be resolved early. This would only // lead to possible proposal resolution failure if the resolve early threshold is not definitive (e.g. < 50% + 1 // of the total voting token's supply). In this case, more voting might actually still be desirable. // Governance mechanisms built on this voting module can apply additional rules on when voting is closed as // appropriate. - assert!(!is_voting_period_over(proposal), error::invalid_state(EPROPOSAL_VOTING_ALREADY_ENDED)); + assert!( + !is_voting_period_over(proposal), + error::invalid_state(EPROPOSAL_VOTING_ALREADY_ENDED) + ); assert!(!proposal.is_resolved, error::invalid_state(EPROPOSAL_ALREADY_RESOLVED)); // Assert this proposal is single-step, or if the proposal is multi-step, it is not in execution yet. - assert!(!simple_map::contains_key(&proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY)) - || *simple_map::borrow(&proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY)) == to_bytes( - &false - ), - error::invalid_state(EMULTI_STEP_PROPOSAL_IN_EXECUTION)); + assert!( + !simple_map::contains_key( + &proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY) + ) || *simple_map::borrow( + &proposal.metadata, &utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY) + ) == to_bytes(&false), + error::invalid_state(EMULTI_STEP_PROPOSAL_IN_EXECUTION) + ); if (should_pass) { proposal.yes_votes = proposal.yes_votes + (num_votes as u128); @@ -402,30 +435,42 @@ module supra_framework::voting { }; event::emit_event( &mut voting_forum.events.vote_events, - VoteEvent { proposal_id, num_votes }, + VoteEvent { proposal_id, num_votes } ); } /// Common checks on if a proposal is resolvable, regardless if the proposal is single-step or multi-step. fun is_proposal_resolvable( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ) acquires VotingForum { - let proposal_state = get_proposal_state(voting_forum_address, proposal_id); - assert!(proposal_state == PROPOSAL_STATE_SUCCEEDED, error::invalid_state(EPROPOSAL_CANNOT_BE_RESOLVED)); + let proposal_state = + get_proposal_state(voting_forum_address, proposal_id); + assert!( + proposal_state == PROPOSAL_STATE_SUCCEEDED, + error::invalid_state(EPROPOSAL_CANNOT_BE_RESOLVED) + ); - let voting_forum = borrow_global_mut>(voting_forum_address); + let voting_forum = + borrow_global_mut>(voting_forum_address); let proposal = table::borrow_mut(&mut voting_forum.proposals, proposal_id); assert!(!proposal.is_resolved, error::invalid_state(EPROPOSAL_ALREADY_RESOLVED)); // We need to make sure that the resolution is happening in // a separate transaction from the last vote to guard against any potential flashloan attacks. - let resolvable_time = to_u64(*simple_map::borrow(&proposal.metadata, &utf8(RESOLVABLE_TIME_METADATA_KEY))); - assert!(timestamp::now_seconds() > resolvable_time, error::invalid_state(ERESOLUTION_CANNOT_BE_ATOMIC)); + let resolvable_time = + to_u64( + *simple_map::borrow( + &proposal.metadata, &utf8(RESOLVABLE_TIME_METADATA_KEY) + ) + ); + assert!( + timestamp::now_seconds() > resolvable_time, + error::invalid_state(ERESOLUTION_CANNOT_BE_ATOMIC) + ); assert!( transaction_context::get_script_hash() == proposal.execution_hash, - error::invalid_argument(EPROPOSAL_EXECUTION_HASH_NOT_MATCHING), + error::invalid_argument(EPROPOSAL_EXECUTION_HASH_NOT_MATCHING) ); } @@ -435,22 +480,28 @@ module supra_framework::voting { /// @param voting_forum_address The address of the forum where the proposals are stored. /// @param proposal_id The proposal id. public fun resolve( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): ProposalType acquires VotingForum { is_proposal_resolvable(voting_forum_address, proposal_id); - let voting_forum = borrow_global_mut>(voting_forum_address); + let voting_forum = + borrow_global_mut>(voting_forum_address); let proposal = table::borrow_mut(&mut voting_forum.proposals, proposal_id); // Assert that the specified proposal is not a multi-step proposal. let multi_step_key = utf8(IS_MULTI_STEP_PROPOSAL_KEY); - let has_multi_step_key = simple_map::contains_key(&proposal.metadata, &multi_step_key); + let has_multi_step_key = + simple_map::contains_key(&proposal.metadata, &multi_step_key); if (has_multi_step_key) { - let is_multi_step_proposal = from_bcs::to_bool(*simple_map::borrow(&proposal.metadata, &multi_step_key)); + let is_multi_step_proposal = + from_bcs::to_bool( + *simple_map::borrow(&proposal.metadata, &multi_step_key) + ); assert!( !is_multi_step_proposal, - error::permission_denied(EMULTI_STEP_PROPOSAL_CANNOT_USE_SINGLE_STEP_RESOLVE_FUNCTION) + error::permission_denied( + EMULTI_STEP_PROPOSAL_CANNOT_USE_SINGLE_STEP_RESOLVE_FUNCTION + ) ); }; @@ -464,8 +515,8 @@ module supra_framework::voting { proposal_id, yes_votes: proposal.yes_votes, no_votes: proposal.no_votes, - resolved_early, - }, + resolved_early + } ); }; event::emit_event( @@ -474,8 +525,8 @@ module supra_framework::voting { proposal_id, yes_votes: proposal.yes_votes, no_votes: proposal.no_votes, - resolved_early, - }, + resolved_early + } ); option::extract(&mut proposal.execution_content) @@ -492,27 +543,31 @@ module supra_framework::voting { public fun resolve_proposal_v2( voting_forum_address: address, proposal_id: u64, - next_execution_hash: vector, + next_execution_hash: vector ) acquires VotingForum { is_proposal_resolvable(voting_forum_address, proposal_id); - let voting_forum = borrow_global_mut>(voting_forum_address); + let voting_forum = + borrow_global_mut>(voting_forum_address); let proposal = table::borrow_mut(&mut voting_forum.proposals, proposal_id); // Update the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY key to indicate that the multi-step proposal is in execution. let multi_step_in_execution_key = utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); if (simple_map::contains_key(&proposal.metadata, &multi_step_in_execution_key)) { - let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut( - &mut proposal.metadata, - &multi_step_in_execution_key - ); + let is_multi_step_proposal_in_execution_value = + simple_map::borrow_mut( + &mut proposal.metadata, + &multi_step_in_execution_key + ); *is_multi_step_proposal_in_execution_value = to_bytes(&true); }; let multi_step_key = utf8(IS_MULTI_STEP_PROPOSAL_KEY); - let is_multi_step = simple_map::contains_key(&proposal.metadata, &multi_step_key) && from_bcs::to_bool( - *simple_map::borrow(&proposal.metadata, &multi_step_key) - ); + let is_multi_step = + simple_map::contains_key(&proposal.metadata, &multi_step_key) + && from_bcs::to_bool( + *simple_map::borrow(&proposal.metadata, &multi_step_key) + ); let next_execution_hash_is_empty = vector::length(&next_execution_hash) == 0; // Assert that if this proposal is single-step, the `next_execution_hash` parameter is empty. @@ -531,10 +586,11 @@ module supra_framework::voting { // Set the `IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY` value to false upon successful resolution of the last step of a multi-step proposal. if (is_multi_step) { - let is_multi_step_proposal_in_execution_value = simple_map::borrow_mut( - &mut proposal.metadata, - &multi_step_in_execution_key - ); + let is_multi_step_proposal_in_execution_value = + simple_map::borrow_mut( + &mut proposal.metadata, + &multi_step_in_execution_key + ); *is_multi_step_proposal_in_execution_value = to_bytes(&false); }; } else { @@ -553,8 +609,8 @@ module supra_framework::voting { proposal_id, yes_votes: proposal.yes_votes, no_votes: proposal.no_votes, - resolved_early, - }, + resolved_early + } ); }; event::emit_event( @@ -563,23 +619,24 @@ module supra_framework::voting { proposal_id, yes_votes: proposal.yes_votes, no_votes: proposal.no_votes, - resolved_early, - }, + resolved_early + } ); } #[view] /// Return the next unassigned proposal id - public fun next_proposal_id(voting_forum_address: address, ): u64 acquires VotingForum { + public fun next_proposal_id( + voting_forum_address: address + ): u64 acquires VotingForum { let voting_forum = borrow_global>(voting_forum_address); voting_forum.next_proposal_id } #[view] public fun get_proposer( - voting_forum_address: address, - proposal_id: u64 + voting_forum_address: address, proposal_id: u64 ): address acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.proposer @@ -587,18 +644,21 @@ module supra_framework::voting { #[view] public fun is_voting_closed( - voting_forum_address: address, - proposal_id: u64 + voting_forum_address: address, proposal_id: u64 ): bool acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); can_be_resolved_early(proposal) || is_voting_period_over(proposal) } /// Return true if the proposal has reached early resolution threshold (if specified). - public fun can_be_resolved_early(proposal: &Proposal): bool { + public fun can_be_resolved_early( + proposal: &Proposal + ): bool { if (option::is_some(&proposal.early_resolution_vote_threshold)) { - let early_resolution_threshold = *option::borrow(&proposal.early_resolution_vote_threshold); - if (proposal.yes_votes >= early_resolution_threshold || proposal.no_votes >= early_resolution_threshold) { + let early_resolution_threshold = + *option::borrow(&proposal.early_resolution_vote_threshold); + if (proposal.yes_votes >= early_resolution_threshold + || proposal.no_votes >= early_resolution_threshold) { return true }; }; @@ -607,8 +667,7 @@ module supra_framework::voting { #[view] public fun get_proposal_metadata( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): SimpleMap> acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.metadata @@ -618,7 +677,7 @@ module supra_framework::voting { public fun get_proposal_metadata_value( voting_forum_address: address, proposal_id: u64, - metadata_key: String, + metadata_key: String ): vector acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); *simple_map::borrow(&proposal.metadata, &metadata_key) @@ -631,15 +690,15 @@ module supra_framework::voting { /// @param proposal_id The proposal id. /// @return Proposal state as an enum value. public fun get_proposal_state( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 acquires VotingForum { if (is_voting_closed(voting_forum_address, proposal_id)) { let proposal = get_proposal(voting_forum_address, proposal_id); let yes_votes = proposal.yes_votes; let no_votes = proposal.no_votes; - if (yes_votes > no_votes && yes_votes + no_votes >= proposal.min_vote_threshold) { + if (yes_votes > no_votes + && yes_votes + no_votes >= proposal.min_vote_threshold) { PROPOSAL_STATE_SUCCEEDED } else { PROPOSAL_STATE_FAILED @@ -652,8 +711,7 @@ module supra_framework::voting { #[view] /// Return the proposal's creation time. public fun get_proposal_creation_secs( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.creation_time_secs @@ -662,8 +720,7 @@ module supra_framework::voting { #[view] /// Return the proposal's expiration time. public fun get_proposal_expiration_secs( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.expiration_secs @@ -672,8 +729,7 @@ module supra_framework::voting { #[view] /// Return the proposal's execution hash. public fun get_execution_hash( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): vector acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.execution_hash @@ -682,8 +738,7 @@ module supra_framework::voting { #[view] /// Return the proposal's minimum vote threshold public fun get_min_vote_threshold( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u128 acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.min_vote_threshold @@ -692,8 +747,7 @@ module supra_framework::voting { #[view] /// Return the proposal's early resolution minimum vote threshold (optionally set) public fun get_early_resolution_vote_threshold( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): Option acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.early_resolution_vote_threshold @@ -702,8 +756,7 @@ module supra_framework::voting { #[view] /// Return the proposal's current vote count (yes_votes, no_votes) public fun get_votes( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): (u128, u128) acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); (proposal.yes_votes, proposal.no_votes) @@ -712,8 +765,7 @@ module supra_framework::voting { #[view] /// Return true if the governance proposal has already been resolved. public fun is_resolved( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): bool acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.is_resolved @@ -721,8 +773,7 @@ module supra_framework::voting { #[view] public fun get_resolution_time_secs( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 acquires VotingForum { let proposal = get_proposal(voting_forum_address, proposal_id); proposal.resolution_time_secs @@ -731,27 +782,30 @@ module supra_framework::voting { #[view] /// Return true if the multi-step governance proposal is in execution. public fun is_multi_step_proposal_in_execution( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): bool acquires VotingForum { let voting_forum = borrow_global>(voting_forum_address); let proposal = table::borrow(&voting_forum.proposals, proposal_id); - let is_multi_step_in_execution_key = utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); + let is_multi_step_in_execution_key = + utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); assert!( simple_map::contains_key(&proposal.metadata, &is_multi_step_in_execution_key), error::invalid_argument(EPROPOSAL_IS_SINGLE_STEP) ); - from_bcs::to_bool(*simple_map::borrow(&proposal.metadata, &is_multi_step_in_execution_key)) + from_bcs::to_bool( + *simple_map::borrow(&proposal.metadata, &is_multi_step_in_execution_key) + ) } /// Return true if the voting period of the given proposal has already ended. - fun is_voting_period_over(proposal: &Proposal): bool { + fun is_voting_period_over( + proposal: &Proposal + ): bool { timestamp::now_seconds() > proposal.expiration_secs } inline fun get_proposal( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): &Proposal acquires VotingForum { let voting_forum = borrow_global>(voting_forum_address); table::borrow(&voting_forum.proposals, proposal_id) @@ -767,7 +821,7 @@ module supra_framework::voting { public fun create_test_proposal_generic( governance: &signer, early_resolution_threshold: Option, - use_generic_create_proposal_function: bool, + use_generic_create_proposal_function: bool ): u64 acquires VotingForum { // Register voting forum and create a proposal. register(governance); @@ -800,7 +854,7 @@ module supra_framework::voting { 10, timestamp::now_seconds() + VOTING_DURATION_SECS, early_resolution_threshold, - metadata, + metadata ) } } @@ -815,10 +869,14 @@ module supra_framework::voting { if (is_multi_step) { let execution_hash = vector::empty(); vector::push_back(&mut execution_hash, 1); - resolve_proposal_v2(voting_forum_address, proposal_id, execution_hash); + resolve_proposal_v2( + voting_forum_address, proposal_id, execution_hash + ); if (finish_multi_step_execution) { - resolve_proposal_v2(voting_forum_address, proposal_id, vector::empty()); + resolve_proposal_v2( + voting_forum_address, proposal_id, vector::empty() + ); }; } else { let proposal = resolve(voting_forum_address, proposal_id); @@ -828,16 +886,14 @@ module supra_framework::voting { #[test_only] public fun create_test_proposal( - governance: &signer, - early_resolution_threshold: Option, + governance: &signer, early_resolution_threshold: Option ): u64 acquires VotingForum { create_test_proposal_generic(governance, early_resolution_threshold, false) } #[test_only] public fun create_proposal_with_empty_execution_hash_should_fail_generic( - governance: &signer, - is_multi_step: bool + governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); let governance_address = signer::address_of(governance); @@ -867,14 +923,16 @@ module supra_framework::voting { 10, 100000, option::none(), - simple_map::create>(), + simple_map::create>() ); }; } #[test(governance = @0x123)] #[expected_failure(abort_code = 0x10004, location = Self)] - public fun create_proposal_with_empty_execution_hash_should_fail(governance: &signer) acquires VotingForum { + public fun create_proposal_with_empty_execution_hash_should_fail( + governance: &signer + ) acquires VotingForum { create_proposal_with_empty_execution_hash_should_fail_generic(governance, false); } @@ -899,8 +957,15 @@ module supra_framework::voting { // Register voting forum and create a proposal. let governance_address = signer::address_of(governance); account::create_account_for_test(governance_address); - let proposal_id = create_test_proposal_generic(governance, option::none(), use_create_multi_step); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 0); + let proposal_id = + create_test_proposal_generic( + governance, option::none(), use_create_multi_step + ); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 0 + ); // Vote. let proof = TestProposal {}; @@ -909,52 +974,60 @@ module supra_framework::voting { // Resolve. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_SUCCEEDED, 1); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_SUCCEEDED, + 1 + ); // This if statement is specifically for the test `test_voting_passed_single_step_can_use_generic_function()`. // It's testing when we have a single-step proposal that was created by the single-step `create_proposal()`, // we should be able to successfully resolve it using the generic `resolve_proposal_v2` function. if (!use_create_multi_step && use_resolve_multi_step) { - resolve_proposal_v2(governance_address, proposal_id, vector::empty()); + resolve_proposal_v2( + governance_address, proposal_id, vector::empty() + ); } else { - resolve_proposal_for_test(governance_address, proposal_id, use_resolve_multi_step, true); + resolve_proposal_for_test( + governance_address, proposal_id, use_resolve_multi_step, true + ); }; let voting_forum = borrow_global>(governance_address); assert!(table::borrow(&voting_forum.proposals, proposal_id).is_resolved, 2); } #[test(supra_framework = @supra_framework, governance = @0x123)] - public entry fun test_voting_passed(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_passed( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_passed_generic(supra_framework, governance, false, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] - public entry fun test_voting_passed_multi_step(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_passed_multi_step( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_passed_generic(supra_framework, governance, true, true); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x5000a, location = Self)] public entry fun test_voting_passed_multi_step_cannot_use_single_step_resolve_function( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { test_voting_passed_generic(supra_framework, governance, true, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] public entry fun test_voting_passed_single_step_can_use_generic_function( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { test_voting_passed_generic(supra_framework, governance, false, true); } #[test_only] public entry fun test_cannot_resolve_twice_generic( - supra_framework: &signer, - governance: &signer, - is_multi_step: bool + supra_framework: &signer, governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -962,8 +1035,13 @@ module supra_framework::voting { // Register voting forum and create a proposal. let governance_address = signer::address_of(governance); account::create_account_for_test(governance_address); - let proposal_id = create_test_proposal_generic(governance, option::none(), is_multi_step); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 0); + let proposal_id = + create_test_proposal_generic(governance, option::none(), is_multi_step); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 0 + ); // Vote. let proof = TestProposal {}; @@ -972,31 +1050,38 @@ module supra_framework::voting { // Resolve. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_SUCCEEDED, 1); - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_SUCCEEDED, + 1 + ); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30003, location = Self)] - public entry fun test_cannot_resolve_twice(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_cannot_resolve_twice( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_cannot_resolve_twice_generic(supra_framework, governance, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30003, location = Self)] public entry fun test_cannot_resolve_twice_multi_step( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { test_cannot_resolve_twice_generic(supra_framework, governance, true); } #[test_only] public entry fun test_voting_passed_early_generic( - supra_framework: &signer, - governance: &signer, - is_multi_step: bool + supra_framework: &signer, governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -1004,12 +1089,20 @@ module supra_framework::voting { // Register voting forum and create a proposal. let governance_address = signer::address_of(governance); account::create_account_for_test(governance_address); - let proposal_id = create_test_proposal_generic(governance, option::some(100), is_multi_step); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 0); + let proposal_id = + create_test_proposal_generic(governance, option::some(100), is_multi_step); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 0 + ); // Assert that IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY has value `false` in proposal.metadata. if (is_multi_step) { - assert!(!is_multi_step_proposal_in_execution(governance_address, 0), 1); + assert!( + !is_multi_step_proposal_in_execution(governance_address, 0), + 1 + ); }; // Vote. @@ -1020,86 +1113,107 @@ module supra_framework::voting { // Resolve early. Need to increase timestamp as resolution cannot happen in the same tx. timestamp::fast_forward_seconds(1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_SUCCEEDED, 2); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_SUCCEEDED, + 2 + ); if (is_multi_step) { // Assert that IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY still has value `false` in proposal.metadata before execution. - assert!(!is_multi_step_proposal_in_execution(governance_address, 0), 3); - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, false); + assert!( + !is_multi_step_proposal_in_execution(governance_address, 0), + 3 + ); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, false + ); // Assert that the multi-step proposal is in execution but not resolved yet. - assert!(is_multi_step_proposal_in_execution(governance_address, 0), 4); - let voting_forum = borrow_global_mut>(governance_address); + assert!( + is_multi_step_proposal_in_execution(governance_address, 0), + 4 + ); + let voting_forum = + borrow_global_mut>(governance_address); let proposal = table::borrow_mut(&mut voting_forum.proposals, proposal_id); assert!(!proposal.is_resolved, 5); }; - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); - let voting_forum = borrow_global_mut>(governance_address); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); + let voting_forum = + borrow_global_mut>(governance_address); assert!(table::borrow(&voting_forum.proposals, proposal_id).is_resolved, 6); // Assert that the IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY value is set back to `false` upon successful resolution of this multi-step proposal. if (is_multi_step) { - assert!(!is_multi_step_proposal_in_execution(governance_address, 0), 7); + assert!( + !is_multi_step_proposal_in_execution(governance_address, 0), + 7 + ); }; } #[test(supra_framework = @supra_framework, governance = @0x123)] - public entry fun test_voting_passed_early(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_passed_early( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_passed_early_generic(supra_framework, governance, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] public entry fun test_voting_passed_early_multi_step( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { test_voting_passed_early_generic(supra_framework, governance, true); } #[test_only] public entry fun test_voting_passed_early_in_same_tx_should_fail_generic( - supra_framework: &signer, - governance: &signer, - is_multi_step: bool + supra_framework: &signer, governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); let governance_address = signer::address_of(governance); account::create_account_for_test(governance_address); - let proposal_id = create_test_proposal_generic(governance, option::some(100), is_multi_step); + let proposal_id = + create_test_proposal_generic(governance, option::some(100), is_multi_step); let proof = TestProposal {}; vote(&proof, governance_address, proposal_id, 40, true); vote(&proof, governance_address, proposal_id, 60, true); let TestProposal {} = proof; // Resolving early should fail since timestamp hasn't changed since the last vote. - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30008, location = Self)] public entry fun test_voting_passed_early_in_same_tx_should_fail( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { - test_voting_passed_early_in_same_tx_should_fail_generic(supra_framework, governance, false); + test_voting_passed_early_in_same_tx_should_fail_generic( + supra_framework, governance, false + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30008, location = Self)] public entry fun test_voting_passed_early_in_same_tx_should_fail_multi_step( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { - test_voting_passed_early_in_same_tx_should_fail_generic(supra_framework, governance, true); + test_voting_passed_early_in_same_tx_should_fail_generic( + supra_framework, governance, true + ); } #[test_only] public entry fun test_voting_failed_generic( - supra_framework: &signer, - governance: &signer, - is_multi_step: bool + supra_framework: &signer, governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -1107,7 +1221,8 @@ module supra_framework::voting { // Register voting forum and create a proposal. let governance_address = signer::address_of(governance); account::create_account_for_test(governance_address); - let proposal_id = create_test_proposal_generic(governance, option::none(), is_multi_step); + let proposal_id = + create_test_proposal_generic(governance, option::none(), is_multi_step); // Vote. let proof = TestProposal {}; @@ -1117,27 +1232,36 @@ module supra_framework::voting { // Resolve. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_FAILED, 1); - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_FAILED, + 1 + ); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30002, location = Self)] - public entry fun test_voting_failed(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_failed( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_failed_generic(supra_framework, governance, false); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30002, location = Self)] - public entry fun test_voting_failed_multi_step(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_failed_multi_step( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_failed_generic(supra_framework, governance, true); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30005, location = Self)] public entry fun test_cannot_vote_after_voting_period_is_over( - supra_framework: signer, - governance: signer + supra_framework: signer, governance: signer ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(&supra_framework); @@ -1154,8 +1278,7 @@ module supra_framework::voting { #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30009, location = Self)] public entry fun test_cannot_vote_after_multi_step_proposal_starts_executing( - supra_framework: signer, - governance: signer + supra_framework: signer, governance: signer ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(&supra_framework); @@ -1163,8 +1286,13 @@ module supra_framework::voting { // Register voting forum and create a proposal. let governance_address = signer::address_of(&governance); account::create_account_for_test(governance_address); - let proposal_id = create_test_proposal_generic(&governance, option::some(100), true); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 0); + let proposal_id = + create_test_proposal_generic(&governance, option::some(100), true); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 0 + ); // Vote. let proof = TestProposal {}; @@ -1172,17 +1300,21 @@ module supra_framework::voting { // Resolve early. timestamp::fast_forward_seconds(1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_SUCCEEDED, 1); - resolve_proposal_for_test(governance_address, proposal_id, true, false); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_SUCCEEDED, + 1 + ); + resolve_proposal_for_test( + governance_address, proposal_id, true, false + ); vote(&proof, governance_address, proposal_id, 100, false); let TestProposal {} = proof; } #[test_only] public entry fun test_voting_failed_early_generic( - supra_framework: &signer, - governance: &signer, - is_multi_step: bool + supra_framework: &signer, governance: &signer, is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -1190,7 +1322,8 @@ module supra_framework::voting { // Register voting forum and create a proposal. let governance_address = signer::address_of(governance); account::create_account_for_test(governance_address); - let proposal_id = create_test_proposal_generic(governance, option::some(100), is_multi_step); + let proposal_id = + create_test_proposal_generic(governance, option::some(100), is_multi_step); // Vote. let proof = TestProposal {}; @@ -1200,21 +1333,28 @@ module supra_framework::voting { // Resolve. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_FAILED, 1); - resolve_proposal_for_test(governance_address, proposal_id, is_multi_step, true); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_FAILED, + 1 + ); + resolve_proposal_for_test( + governance_address, proposal_id, is_multi_step, true + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30002, location = Self)] - public entry fun test_voting_failed_early(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_voting_failed_early( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { test_voting_failed_early_generic(supra_framework, governance, true); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x30002, location = Self)] public entry fun test_voting_failed_early_multi_step( - supra_framework: &signer, - governance: &signer + supra_framework: &signer, governance: &signer ) acquires VotingForum { test_voting_failed_early_generic(supra_framework, governance, false); } @@ -1223,7 +1363,7 @@ module supra_framework::voting { public entry fun test_cannot_set_min_threshold_higher_than_early_resolution_generic( supra_framework: &signer, governance: &signer, - is_multi_step: bool, + is_multi_step: bool ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); @@ -1235,31 +1375,40 @@ module supra_framework::voting { #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_cannot_set_min_threshold_higher_than_early_resolution( - supra_framework: &signer, - governance: &signer, + supra_framework: &signer, governance: &signer ) acquires VotingForum { - test_cannot_set_min_threshold_higher_than_early_resolution_generic(supra_framework, governance, false); + test_cannot_set_min_threshold_higher_than_early_resolution_generic( + supra_framework, governance, false + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_cannot_set_min_threshold_higher_than_early_resolution_multi_step( - supra_framework: &signer, - governance: &signer, + supra_framework: &signer, governance: &signer ) acquires VotingForum { - test_cannot_set_min_threshold_higher_than_early_resolution_generic(supra_framework, governance, true); + test_cannot_set_min_threshold_higher_than_early_resolution_generic( + supra_framework, governance, true + ); } #[test(supra_framework = @supra_framework, governance = @0x123)] - public entry fun test_replace_execution_hash(supra_framework: &signer, governance: &signer) acquires VotingForum { + public entry fun test_replace_execution_hash( + supra_framework: &signer, governance: &signer + ) acquires VotingForum { account::create_account_for_test(@supra_framework); timestamp::set_time_has_started_for_testing(supra_framework); // Register voting forum and create a proposal. let governance_address = signer::address_of(governance); account::create_account_for_test(governance_address); - let proposal_id = create_test_proposal_generic(governance, option::none(), true); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_PENDING, 0); + let proposal_id = + create_test_proposal_generic(governance, option::none(), true); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_PENDING, + 0 + ); // Vote. let proof = TestProposal {}; @@ -1268,7 +1417,11 @@ module supra_framework::voting { // Resolve. timestamp::fast_forward_seconds(VOTING_DURATION_SECS + 1); - assert!(get_proposal_state(governance_address, proposal_id) == PROPOSAL_STATE_SUCCEEDED, 1); + assert!( + get_proposal_state(governance_address, proposal_id) + == PROPOSAL_STATE_SUCCEEDED, + 1 + ); resolve_proposal_v2(governance_address, proposal_id, vector[10u8]); let voting_forum = borrow_global>(governance_address); diff --git a/aptos-move/framework/supra-framework/sources/voting.spec.move b/aptos-move/framework/supra-framework/sources/voting.spec.move index 3da5c97ad801d..444087b1a983d 100644 --- a/aptos-move/framework/supra-framework/sources/voting.spec.move +++ b/aptos-move/framework/supra-framework/sources/voting.spec.move @@ -51,7 +51,8 @@ spec supra_framework::voting { // Creation of 4 new event handles changes the account's `guid_creation_num` aborts_if !exists(addr); let register_account = global(addr); - aborts_if register_account.guid_creation_num + 4 >= account::MAX_GUID_CREATION_NUM; + aborts_if register_account.guid_creation_num + 4 + >= account::MAX_GUID_CREATION_NUM; aborts_if register_account.guid_creation_num + 4 > MAX_U64; // `type_info::type_of()` may abort if the type parameter is not a struct aborts_if !type_info::spec_is_struct(); @@ -67,15 +68,18 @@ spec supra_framework::voting { min_vote_threshold: u128, expiration_secs: u64, early_resolution_vote_threshold: Option, - metadata: SimpleMap>, + metadata: SimpleMap> ): u64 { use supra_framework::chain_status; requires chain_status::is_operating(); - include CreateProposalAbortsIfAndEnsures{is_multi_step_proposal: false}; + include CreateProposalAbortsIfAndEnsures { + is_multi_step_proposal: false + }; // property 1: Verify the proposal_id of the newly created proposal. /// [high-level-req-1] - ensures result == old(global>(voting_forum_address)).next_proposal_id; + ensures result + == old(global>(voting_forum_address)).next_proposal_id; } // The min_vote_threshold lower thanearly_resolution_vote_threshold. @@ -92,14 +96,15 @@ spec supra_framework::voting { expiration_secs: u64, early_resolution_vote_threshold: Option, metadata: SimpleMap>, - is_multi_step_proposal: bool, + is_multi_step_proposal: bool ): u64 { use supra_framework::chain_status; requires chain_status::is_operating(); include CreateProposalAbortsIfAndEnsures; // property 1: Verify the proposal_id of the newly created proposal. - ensures result == old(global>(voting_forum_address)).next_proposal_id; + ensures result + == old(global>(voting_forum_address)).next_proposal_id; } spec schema CreateProposalAbortsIfAndEnsures { @@ -114,24 +119,34 @@ spec supra_framework::voting { let proposal_id = voting_forum.next_proposal_id; aborts_if !exists>(voting_forum_address); - aborts_if table::spec_contains(voting_forum.proposals,proposal_id); - aborts_if len(early_resolution_vote_threshold.vec) != 0 && min_vote_threshold > early_resolution_vote_threshold.vec[0]; + aborts_if table::spec_contains(voting_forum.proposals, proposal_id); + aborts_if len(early_resolution_vote_threshold.vec) != 0 + && min_vote_threshold > early_resolution_vote_threshold.vec[0]; aborts_if !std::string::spec_internal_check_utf8(IS_MULTI_STEP_PROPOSAL_KEY); - aborts_if !std::string::spec_internal_check_utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); + aborts_if !std::string::spec_internal_check_utf8( + IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY + ); aborts_if len(execution_hash) == 0; let execution_key = std::string::spec_utf8(IS_MULTI_STEP_PROPOSAL_KEY); aborts_if simple_map::spec_contains_key(metadata, execution_key); aborts_if voting_forum.next_proposal_id + 1 > MAX_U64; - let is_multi_step_in_execution_key = std::string::spec_utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); - aborts_if is_multi_step_proposal && simple_map::spec_contains_key(metadata, is_multi_step_in_execution_key); - - let post post_voting_forum = global>(voting_forum_address); - let post post_metadata = table::spec_get(post_voting_forum.proposals, proposal_id).metadata; + let is_multi_step_in_execution_key = std::string::spec_utf8( + IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY + ); + aborts_if is_multi_step_proposal + && simple_map::spec_contains_key(metadata, is_multi_step_in_execution_key); + + let post post_voting_forum = global>( + voting_forum_address + ); + let post post_metadata = table::spec_get(post_voting_forum.proposals, proposal_id) + .metadata; ensures post_voting_forum.next_proposal_id == voting_forum.next_proposal_id + 1; // property 1: Ensure that newly created proposals exist in the voting forum proposals table. ensures table::spec_contains(post_voting_forum.proposals, proposal_id); ensures if (is_multi_step_proposal) { - simple_map::spec_get(post_metadata, is_multi_step_in_execution_key) == std::bcs::serialize(false) + simple_map::spec_get(post_metadata, is_multi_step_in_execution_key) + == std::bcs::serialize(false) } else { !simple_map::spec_contains_key(post_metadata, is_multi_step_in_execution_key) }; @@ -142,7 +157,7 @@ spec supra_framework::voting { voting_forum_address: address, proposal_id: u64, num_votes: u64, - should_pass: bool, + should_pass: bool ) { use supra_framework::chain_status; // Ensures existence of Timestamp @@ -160,15 +175,26 @@ spec supra_framework::voting { aborts_if proposal.is_resolved; aborts_if !exists(@supra_framework); // Assert this proposal is single-step, or if the proposal is multi-step, it is not in execution yet. - aborts_if !std::string::spec_internal_check_utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); - let execution_key = std::string::spec_utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); - aborts_if simple_map::spec_contains_key(proposal.metadata, execution_key) && - simple_map::spec_get(proposal.metadata, execution_key) != std::bcs::serialize(false); - aborts_if if (should_pass) { proposal.yes_votes + num_votes > MAX_U128 } else { proposal.no_votes + num_votes > MAX_U128 }; + aborts_if !std::string::spec_internal_check_utf8( + IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY + ); + let execution_key = std::string::spec_utf8( + IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY + ); + aborts_if simple_map::spec_contains_key(proposal.metadata, execution_key) + && simple_map::spec_get(proposal.metadata, execution_key) + != std::bcs::serialize(false); + aborts_if if (should_pass) { + proposal.yes_votes + num_votes > MAX_U128 + } else { + proposal.no_votes + num_votes > MAX_U128 + }; aborts_if !std::string::spec_internal_check_utf8(RESOLVABLE_TIME_METADATA_KEY); - let post post_voting_forum = global>(voting_forum_address); + let post post_voting_forum = global>( + voting_forum_address + ); let post post_proposal = table::spec_get(post_voting_forum.proposals, proposal_id); ensures if (should_pass) { post_proposal.yes_votes == proposal.yes_votes + num_votes @@ -177,12 +203,12 @@ spec supra_framework::voting { }; let timestamp_secs_bytes = std::bcs::serialize(timestamp::spec_now_seconds()); let key = std::string::spec_utf8(RESOLVABLE_TIME_METADATA_KEY); - ensures simple_map::spec_get(post_proposal.metadata, key) == timestamp_secs_bytes; + ensures simple_map::spec_get(post_proposal.metadata, key) + == timestamp_secs_bytes; } spec is_proposal_resolvable( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ) { use supra_framework::chain_status; // Ensures existence of Timestamp @@ -198,24 +224,42 @@ spec supra_framework::voting { let voting_forum = global>(voting_forum_address); let proposal = table::spec_get(voting_forum.proposals, proposal_id); - let voting_closed = spec_is_voting_closed(voting_forum_address, proposal_id); + let voting_closed = spec_is_voting_closed( + voting_forum_address, proposal_id + ); // Avoid Overflow - aborts_if voting_closed && (proposal.yes_votes <= proposal.no_votes || proposal.yes_votes + proposal.no_votes < proposal.min_vote_threshold); + aborts_if voting_closed + && ( + proposal.yes_votes <= proposal.no_votes + || proposal.yes_votes + proposal.no_votes + < proposal.min_vote_threshold + ); // Resolvable_time Properties aborts_if !voting_closed; aborts_if proposal.is_resolved; aborts_if !std::string::spec_internal_check_utf8(RESOLVABLE_TIME_METADATA_KEY); - aborts_if !simple_map::spec_contains_key(proposal.metadata, std::string::spec_utf8(RESOLVABLE_TIME_METADATA_KEY)); - aborts_if !from_bcs::deserializable(simple_map::spec_get(proposal.metadata, std::string::spec_utf8(RESOLVABLE_TIME_METADATA_KEY))); - aborts_if timestamp::spec_now_seconds() <= from_bcs::deserialize(simple_map::spec_get(proposal.metadata, std::string::spec_utf8(RESOLVABLE_TIME_METADATA_KEY))); - aborts_if transaction_context::spec_get_script_hash() != proposal.execution_hash; - } - - spec resolve( - voting_forum_address: address, - proposal_id: u64, - ): ProposalType { + aborts_if !simple_map::spec_contains_key( + proposal.metadata, std::string::spec_utf8(RESOLVABLE_TIME_METADATA_KEY) + ); + aborts_if !from_bcs::deserializable( + simple_map::spec_get( + proposal.metadata, std::string::spec_utf8(RESOLVABLE_TIME_METADATA_KEY) + ) + ); + aborts_if timestamp::spec_now_seconds() + <= from_bcs::deserialize( + simple_map::spec_get( + proposal.metadata, std::string::spec_utf8( + RESOLVABLE_TIME_METADATA_KEY + ) + ) + ); + aborts_if transaction_context::spec_get_script_hash() + != proposal.execution_hash; + } + + spec resolve(voting_forum_address: address, proposal_id: u64): ProposalType { use supra_framework::chain_status; // Ensures existence of Timestamp requires chain_status::is_operating(); @@ -225,11 +269,21 @@ spec supra_framework::voting { let voting_forum = global>(voting_forum_address); let proposal = table::spec_get(voting_forum.proposals, proposal_id); let multi_step_key = std::string::spec_utf8(IS_MULTI_STEP_PROPOSAL_KEY); - let has_multi_step_key = simple_map::spec_contains_key(proposal.metadata, multi_step_key); - aborts_if has_multi_step_key && !from_bcs::deserializable(simple_map::spec_get(proposal.metadata, multi_step_key)); - aborts_if has_multi_step_key && from_bcs::deserialize(simple_map::spec_get(proposal.metadata, multi_step_key)); - - let post post_voting_forum = global>(voting_forum_address); + let has_multi_step_key = simple_map::spec_contains_key( + proposal.metadata, multi_step_key + ); + aborts_if has_multi_step_key + && !from_bcs::deserializable( + simple_map::spec_get(proposal.metadata, multi_step_key) + ); + aborts_if has_multi_step_key + && from_bcs::deserialize( + simple_map::spec_get(proposal.metadata, multi_step_key) + ); + + let post post_voting_forum = global>( + voting_forum_address + ); let post post_proposal = table::spec_get(post_voting_forum.proposals, proposal_id); aborts_if !exists(@supra_framework); // property 3: Ensure that proposal is successfully resolved. @@ -243,9 +297,7 @@ spec supra_framework::voting { } spec resolve_proposal_v2( - voting_forum_address: address, - proposal_id: u64, - next_execution_hash: vector, + voting_forum_address: address, proposal_id: u64, next_execution_hash: vector ) { use supra_framework::chain_status; pragma verify_duration_estimate = 300; @@ -255,38 +307,68 @@ spec supra_framework::voting { include IsProposalResolvableAbortsIf; let voting_forum = global>(voting_forum_address); let proposal = table::spec_get(voting_forum.proposals, proposal_id); - let post post_voting_forum = global>(voting_forum_address); + let post post_voting_forum = global>( + voting_forum_address + ); let post post_proposal = table::spec_get(post_voting_forum.proposals, proposal_id); - let multi_step_in_execution_key = std::string::spec_utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); - aborts_if !std::string::spec_internal_check_utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); + let multi_step_in_execution_key = std::string::spec_utf8( + IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY + ); + aborts_if !std::string::spec_internal_check_utf8( + IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY + ); aborts_if !std::string::spec_internal_check_utf8(IS_MULTI_STEP_PROPOSAL_KEY); - ensures (simple_map::spec_contains_key(proposal.metadata, multi_step_in_execution_key) && len(next_execution_hash) != 0) ==> - simple_map::spec_get(post_proposal.metadata, multi_step_in_execution_key) == std::bcs::serialize(true); - ensures (simple_map::spec_contains_key(proposal.metadata, multi_step_in_execution_key) && - (len(next_execution_hash) == 0 && !is_multi_step)) ==> - simple_map::spec_get(post_proposal.metadata, multi_step_in_execution_key) == std::bcs::serialize(true); + ensures ( + simple_map::spec_contains_key(proposal.metadata, multi_step_in_execution_key) + && len(next_execution_hash) != 0 + ) ==> + simple_map::spec_get(post_proposal.metadata, multi_step_in_execution_key) + == std::bcs::serialize(true); + ensures ( + simple_map::spec_contains_key(proposal.metadata, multi_step_in_execution_key) + && (len(next_execution_hash) == 0 + && !is_multi_step) + ) ==> + simple_map::spec_get(post_proposal.metadata, multi_step_in_execution_key) + == std::bcs::serialize(true); let multi_step_key = std::string::spec_utf8(IS_MULTI_STEP_PROPOSAL_KEY); - aborts_if simple_map::spec_contains_key(proposal.metadata, multi_step_key) && - !from_bcs::deserializable(simple_map::spec_get(proposal.metadata, multi_step_key)); - let is_multi_step = simple_map::spec_contains_key(proposal.metadata, multi_step_key) && - from_bcs::deserialize(simple_map::spec_get(proposal.metadata, multi_step_key)); + aborts_if simple_map::spec_contains_key(proposal.metadata, multi_step_key) + && !from_bcs::deserializable( + simple_map::spec_get(proposal.metadata, multi_step_key) + ); + let is_multi_step = simple_map::spec_contains_key( + proposal.metadata, multi_step_key + ) && from_bcs::deserialize( + simple_map::spec_get(proposal.metadata, multi_step_key) + ); aborts_if !is_multi_step && len(next_execution_hash) != 0; - aborts_if len(next_execution_hash) == 0 && !exists(@supra_framework); - aborts_if len(next_execution_hash) == 0 && is_multi_step && !simple_map::spec_contains_key(proposal.metadata, multi_step_in_execution_key); + aborts_if len(next_execution_hash) == 0 + && !exists(@supra_framework); + aborts_if len(next_execution_hash) == 0 + && is_multi_step + && !simple_map::spec_contains_key( + proposal.metadata, multi_step_in_execution_key + ); // property 4: For single-step proposals, it ensures that the next_execution_hash parameter is empty and resolves the proposal. /// [high-level-req-4] - ensures len(next_execution_hash) == 0 ==> post_proposal.resolution_time_secs == timestamp::spec_now_seconds(); - ensures len(next_execution_hash) == 0 ==> post_proposal.is_resolved == true; - ensures (len(next_execution_hash) == 0 && is_multi_step) ==> simple_map::spec_get(post_proposal.metadata, multi_step_in_execution_key) == std::bcs::serialize(false); + ensures len(next_execution_hash) == 0 ==> + post_proposal.resolution_time_secs == timestamp::spec_now_seconds(); + ensures len(next_execution_hash) == 0 ==> + post_proposal.is_resolved == true; + ensures (len(next_execution_hash) == 0 && is_multi_step) ==> + simple_map::spec_get(post_proposal.metadata, multi_step_in_execution_key) + == std::bcs::serialize(false); // property 4: For multi-step proposals, it ensures that the next_execution_hash parameter contains the hash of the next step. - ensures len(next_execution_hash) != 0 ==> post_proposal.execution_hash == next_execution_hash; + ensures len(next_execution_hash) != 0 ==> + post_proposal.execution_hash == next_execution_hash; } spec next_proposal_id(voting_forum_address: address): u64 { aborts_if !exists>(voting_forum_address); - ensures result == global>(voting_forum_address).next_proposal_id; + ensures result + == global>(voting_forum_address).next_proposal_id; } spec is_voting_closed(voting_forum_address: address, proposal_id: u64): bool { @@ -295,13 +377,17 @@ spec supra_framework::voting { requires chain_status::is_operating(); include AbortsIfNotContainProposalID; aborts_if !exists(@supra_framework); - ensures result == spec_is_voting_closed(voting_forum_address, proposal_id); + ensures result + == spec_is_voting_closed(voting_forum_address, proposal_id); } - spec fun spec_is_voting_closed(voting_forum_address: address, proposal_id: u64): bool { + spec fun spec_is_voting_closed( + voting_forum_address: address, proposal_id: u64 + ): bool { let voting_forum = global>(voting_forum_address); let proposal = table::spec_get(voting_forum.proposals, proposal_id); - spec_can_be_resolved_early(proposal) || is_voting_period_over(proposal) + spec_can_be_resolved_early(proposal) + || is_voting_period_over(proposal) } spec can_be_resolved_early(proposal: &Proposal): bool { @@ -311,15 +397,12 @@ spec supra_framework::voting { spec fun spec_can_be_resolved_early(proposal: Proposal): bool { if (option::spec_is_some(proposal.early_resolution_vote_threshold)) { - let early_resolution_threshold = option::spec_borrow(proposal.early_resolution_vote_threshold); - if (proposal.yes_votes >= early_resolution_threshold || proposal.no_votes >= early_resolution_threshold) { - true - } else{ - false - } - } else { - false - } + let early_resolution_threshold = + option::spec_borrow(proposal.early_resolution_vote_threshold); + if (proposal.yes_votes >= early_resolution_threshold + || proposal.no_votes >= early_resolution_threshold) { true } + else { false } + } else { false } } spec fun spec_get_proposal_state( @@ -328,8 +411,14 @@ spec supra_framework::voting { voting_forum: VotingForum ): u64 { let proposal = table::spec_get(voting_forum.proposals, proposal_id); - let voting_closed = spec_is_voting_closed(voting_forum_address, proposal_id); - let proposal_vote_cond = (proposal.yes_votes > proposal.no_votes && proposal.yes_votes + proposal.no_votes >= proposal.min_vote_threshold); + let voting_closed = + spec_is_voting_closed(voting_forum_address, proposal_id); + let proposal_vote_cond = + ( + proposal.yes_votes > proposal.no_votes + && proposal.yes_votes + proposal.no_votes + >= proposal.min_vote_threshold + ); if (voting_closed && proposal_vote_cond) { PROPOSAL_STATE_SUCCEEDED } else if (voting_closed && !proposal_vote_cond) { @@ -340,8 +429,7 @@ spec supra_framework::voting { } spec fun spec_get_proposal_expiration_secs( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 { let voting_forum = global>(voting_forum_address); let proposal = table::spec_get(voting_forum.proposals, proposal_id); @@ -349,8 +437,7 @@ spec supra_framework::voting { } spec get_proposal_state( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 { use supra_framework::chain_status; @@ -362,13 +449,11 @@ spec supra_framework::voting { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); - ensures result == spec_get_proposal_state(voting_forum_address, proposal_id, voting_forum); + ensures result + == spec_get_proposal_state(voting_forum_address, proposal_id, voting_forum); } - spec get_proposer( - voting_forum_address: address, - proposal_id: u64, - ): address { + spec get_proposer(voting_forum_address: address, proposal_id: u64): address { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); let proposal = table::spec_get(voting_forum.proposals, proposal_id); @@ -376,8 +461,7 @@ spec supra_framework::voting { } spec get_proposal_creation_secs( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); @@ -386,16 +470,17 @@ spec supra_framework::voting { } spec get_proposal_expiration_secs( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 { include AbortsIfNotContainProposalID; - ensures result == spec_get_proposal_expiration_secs(voting_forum_address, proposal_id); + ensures result + == spec_get_proposal_expiration_secs( + voting_forum_address, proposal_id + ); } spec get_resolution_time_secs( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u64 { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); @@ -404,8 +489,7 @@ spec supra_framework::voting { } spec get_execution_hash( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): vector { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); @@ -414,8 +498,7 @@ spec supra_framework::voting { } spec get_min_vote_threshold( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): u128 { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); @@ -424,8 +507,7 @@ spec supra_framework::voting { } spec get_early_resolution_vote_threshold( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): Option { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); @@ -434,8 +516,7 @@ spec supra_framework::voting { } spec get_proposal_metadata( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): SimpleMap> { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); @@ -444,9 +525,7 @@ spec supra_framework::voting { } spec get_proposal_metadata_value( - voting_forum_address: address, - proposal_id: u64, - metadata_key: String, + voting_forum_address: address, proposal_id: u64, metadata_key: String ): vector { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); @@ -455,10 +534,9 @@ spec supra_framework::voting { ensures result == simple_map::spec_get(proposal.metadata, metadata_key); } - spec get_votes( - voting_forum_address: address, - proposal_id: u64, - ): (u128, u128) { + spec get_votes(voting_forum_address: address, proposal_id: u64): ( + u128, u128 + ) { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); let proposal = table::spec_get(voting_forum.proposals, proposal_id); @@ -466,10 +544,7 @@ spec supra_framework::voting { ensures result_2 == proposal.no_votes; } - spec is_resolved( - voting_forum_address: address, - proposal_id: u64, - ): bool { + spec is_resolved(voting_forum_address: address, proposal_id: u64): bool { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); let proposal = table::spec_get(voting_forum.proposals, proposal_id); @@ -485,18 +560,23 @@ spec supra_framework::voting { } spec is_multi_step_proposal_in_execution( - voting_forum_address: address, - proposal_id: u64, + voting_forum_address: address, proposal_id: u64 ): bool { include AbortsIfNotContainProposalID; let voting_forum = global>(voting_forum_address); - let proposal = table::spec_get(voting_forum.proposals,proposal_id); - aborts_if !std::string::spec_internal_check_utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); - - let execution_key = std::string::spec_utf8(IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY); - aborts_if !simple_map::spec_contains_key(proposal.metadata,execution_key); - - let is_multi_step_in_execution_key = simple_map::spec_get(proposal.metadata,execution_key); + let proposal = table::spec_get(voting_forum.proposals, proposal_id); + aborts_if !std::string::spec_internal_check_utf8( + IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY + ); + + let execution_key = std::string::spec_utf8( + IS_MULTI_STEP_PROPOSAL_IN_EXECUTION_KEY + ); + aborts_if !simple_map::spec_contains_key(proposal.metadata, execution_key); + + let is_multi_step_in_execution_key = simple_map::spec_get( + proposal.metadata, execution_key + ); aborts_if !from_bcs::deserializable(is_multi_step_in_execution_key); ensures result == from_bcs::deserialize(is_multi_step_in_execution_key);