Skip to content

Commit

Permalink
Warning about using zero address as ownership in SwayBook (FuelLabs#2127
Browse files Browse the repository at this point in the history
)

* Add warning about BASE_ASSET_ID and write example ownership contract

* Typos

* Run forc fmt

* Update docs/src/blockchain-development/access_control.md

Co-authored-by: John Adler <[email protected]>

* Update docs/src/blockchain-development/access_control.md

Co-authored-by: John Adler <[email protected]>

* Update to account for BASE_ASSET_ID now to be a ContractID and refer to the zero address in general

* Typo

* Commit suggestions

* Update docs/src/blockchain-development/access_control.md

Co-authored-by: John Adler <[email protected]>

Co-authored-by: John Adler <[email protected]>
Co-authored-by: Mohammad Fawaz <[email protected]>
  • Loading branch information
3 people authored Jul 1, 2022
1 parent bffa13c commit 02c010c
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 1 deletion.
16 changes: 16 additions & 0 deletions docs/src/blockchain-development/access_control.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,19 @@ The `msg_sender` function works as follows:
- If the caller is a contract, then `Result::Ok(Sender)` is returned with the `ContractId` sender variant.
- If the caller is external (i.e. from a script), then all coin input owners in the transaction are checked. If all owners are the same, then `Result::Ok(Sender)` is returned with the `Address` sender variant.
- If the caller is external and coin input owners are different, then the caller cannot be determined and a `Result::Err(AuthError)` is returned.

## Contract Ownership

Many contracts require some form of ownership for access control. To accomplish this, it is recommended that a storage variable of type `Option<Identity>` is used to keep track of the owner. This allows setting and revoking ownership using the variants `Some(..)` and `None` respectively. This is better, safer, and more readable than using the `Identity` type directly where revoking ownership has to be done using some magic value such as `std::constants::ZERO_B256` or otherwise.

The following is an example of how to properly set ownership of a contract:

```sway
{{#include ../../../examples/ownership/src/main.sw:set_owner_example}}
```

The following is an example of how to properly revoke ownership of a contract:

```sway
{{#include ../../../examples/ownership/src/main.sw:revoke_owner_example}}
```
2 changes: 1 addition & 1 deletion examples/identity/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl IdentityExample for Contract {
revert(0);
}
};
// ANCHOR_END: identity_to_contract_ids
// ANCHOR_END: identity_to_contract_id
}

fn different_executions(my_identity: Identity) {
Expand Down
14 changes: 14 additions & 0 deletions examples/ownership/Forc.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[[package]]
name = 'core'
source = 'path+from-root-636C01A16D569E34'
dependencies = []

[[package]]
name = 'ownership'
source = 'root'
dependencies = ['std']

[[package]]
name = 'std'
source = 'path+from-root-636C01A16D569E34'
dependencies = ['core']
8 changes: 8 additions & 0 deletions examples/ownership/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "ownership"

[dependencies]
std = { path = "../../sway-lib-std" }
31 changes: 31 additions & 0 deletions examples/ownership/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
contract;

use std::{identity::Identity, option::Option};

abi OwnershipExample {
#[storage(write)]fn revoke_ownership();
#[storage(write)]fn set_owner(identity: Identity);
#[storage(read)]fn owner() -> Option<Identity>;
}

storage {
owner: Option<Identity>,
}

impl OwnershipExample for Contract {
// ANCHOR: revoke_owner_example
#[storage(write)]fn revoke_ownership() {
storage.owner = Option::None();
}
// ANCHOR_END: revoke_owner_example

// ANCHOR: set_owner_example
#[storage(write)]fn set_owner(identity: Identity) {
storage.owner = Option::Some(identity);
}
// ANCHOR_END: set_owner_example

#[storage(read)]fn owner() -> Option<Identity> {
storage.owner
}
}

0 comments on commit 02c010c

Please sign in to comment.