Aptos Move: Mastering Access Control to Write Secure Modules

Moncayo Labs
Cryptocurrency Scripts
3 min readAug 7, 2024

Demystifying Access Control: onlyOwner Functions in Aptos Smart Contracts

Why You Should Care

In 2022 crypto hacking amounted to $3.7 billion stolen, primarily from DeFi Protocols, in 2023 $1.7 billion were stolen (source: Chainalysis). Whilst the number decreased, DeFi exploits remain a significant threat to the blockchain space.

Most blockchain-related hacks stem from a mismatch in access rights, ie an imbalance between building a decentralised DeFi protocol that will be self-sufficient and community-maintained and at the same time protect access to critical protocol infrastructure to avoid malicious behaviour.

Thus, as a smart contract developer, access control isn’t just important, it’s essential for keeping your digital fortress secure and your users happy.

How to Handle Access Rights in Aptos Move

Currently, there is no OpenZeppelin contract library for Aptos Move. Hence, it is not a simply as adding an onlyOwner modifier to your function as you might do in Solidity.

In Aptos, we have to come up with our own assert statements to assure access control to critical endpoints. In the example code below, we have two types of function withdraw and deposit.

deposit has no access control and anyone can use it, because we do not pass in the &signer as a functional argument. The account: &signer can be thought of as something very similar to the msg.sender in Solidity. In the deposit function, we do not care who the msg.sender is.

If we want to be able to verify and check who sent the transaction, we would need to pass in the account: &signer . Then, we can build our own user types and their relevant access types by creating helper functions, such as the is_owner() provided as an example here.

Thus transaction usually pass in the account: &signer, whilst simple blockchain calls do not pass in any caller information.


#[view]
/// @notice Returns true if address is the contract owner.
/// @param Address to be checked.
public fun is_owner(account: address): bool acquires Settings{
let my_module = borrow_global<MyModuleStorage>(RESOURCE_ACCOUNT);
return (my_module.admin == account)
}

// withdraw function with access control
public entry fun withdraw(account: &signer, amount: u64): Coin acquires Coin {
assert!(is_owner(signer::address_of(account)), error::permission_denied(EONLY_OWNER_CAN_WITHDRAW));
let balance = &mut borrow_global_mut<Coin>(signer::address_of(account)).amount;
*balance = *balance - amount;
Coin { amount }
}

// deposit function without any access control
public entry fun deposit(account: address, coin: Coin) acquires Coin {
let balance = &mut borrow_global_mut<Coin>(account).amount;
*balance = *balance + coin.amount;
Coin { amount: _ } = coin;
}

Best Real-World Permissions Practise in Aptos Move

To give you a real-world example of one the largest players on Aptos. See how Pontem Network is handling access permissions for creating new liquid token swaps:

/// When called from wrong account.
const ERR_NOT_ENOUGH_PERMISSIONS: u64 = 1701;

public entry fun initialize_lp_account(
liquidswap_admin: &signer,
lp_coin_metadata_serialized: vector<u8>,
lp_coin_code: vector<u8>
) {
assert!(signer::address_of(liquidswap_admin) == @liquidswap, ERR_NOT_ENOUGH_PERMISSIONS);

// creates new LP resource acccount and initializes it
}

In this example, the pontem team is comparing the transaction signer to a hard-coded @liquidswap address. If the signer address does not match this address, the custom ERR_NOT_ENOUGH_PERMISSIONS is thrown.

If this short intro into user access control was somewhat helpful to you, please help us with a little clap. 👏 👏 👏

What do you want to learn about next? — Let us know in the comments below. 💬

If you want this blockchain resource to continue to exist, please follow or subscribe to the mailing list. — Thank you. 🐤

References:

Chainalysis DeFi Hacks:

The Pontem Network code:

--

--

Moncayo Labs
Cryptocurrency Scripts

Active Supporter of the Aptos Move Movement | Web3 Move Development Tutorials