MultiOwnable¶
Overview¶
MultiOwnable is an abstract contract providing multi-owner access control. Unlike OpenZeppelin's Ownable which has a single owner, MultiOwnable allows multiple addresses to have owner privileges simultaneously.
- Kind: Abstract Contract
- License: Sharia
- Solidity: ^0.8.21
- Source:
lib/multiownable.sol
Inheritance Chain (C3 Linearized)¶
No base contracts; this contract has no parents.
Immediate Parents¶
None (root of its hierarchy).
What This Means For Players¶
Plain English Summary: MultiOwnable allows shared control - it lets multiple people manage the same thing. Instead of having just one admin, a contract can have many admins who all have equal power. This is essential for the Dysnomia ecosystem where game contracts need to interact with each other.
Real-World Analogy: Think of a shared bank account that has multiple signatories. Any of the signatories can make transactions - you don't need everyone to approve. MultiOwnable works the same way: if you're on the list of owners, you can control the contract.
How It Affects Your Gameplay: - Shared access - Your LAU, SHIO, and other tokens may have multiple owners (you + game contracts) - Chain of trust - Game contracts add each other as owners to enable coordination - Revocable - Owners can be added or removed by existing owners
State Variables¶
| Variable | Type | Visibility | Mutability | Initial Value | NatSpec |
|---|---|---|---|---|---|
_owners |
mapping(address => bool) |
private | mutable | `` |
Modifiers¶
| Modifier | Parameters | NatSpec |
|---|---|---|
onlyOwners |
(none) |
Events¶
| Event | Parameters | Anonymous | NatSpec |
|---|---|---|---|
OwnershipUpdate |
address indexed newOwner, bool indexed state | no |
Errors¶
| Error | Parameters | NatSpec |
|---|---|---|
OwnableUnauthorizedAccount |
address origin, address account, address what | |
OwnableInvalidOwner |
address origin, address owner, address what |
Constructor¶
constructor¶
- Parameters: address initialOwner
Functions¶
External & Public¶
owner¶
- Visibility: external
- State Mutability: view
- Virtual: yes
- Returns: address
owner¶
- Visibility: public
- State Mutability: view
- Virtual: yes
- Parameters: address cOwner
- Returns: bool
renounceOwnership¶
- Visibility: public
- Virtual: yes
- Modifiers:
onlyOwners - Parameters: address toRemove
addOwner¶
- Visibility: public
- Virtual: yes
- Modifiers:
onlyOwners - Parameters: address newOwner
Internal¶
_checkOwner¶
- Visibility: internal
- State Mutability: view
- Virtual: yes
_changeOwnership¶
- Visibility: internal
- Virtual: yes
- Parameters: address cOwner, bool cState
Modifier¶
onlyOwners¶
- Description: Restricts function access to owners only - Checks: Both msg.sender AND tx.origin - allows if either is an ownerContract Interactions¶
Depended On By¶
- DYSNOMIA - All tokens inherit this
- Every contract in the ecosystem
Special Mechanisms¶
Dual Sender Check¶
The _checkOwner function checks both:
This allows: - Direct calls from owner addresses - Calls through contracts where tx.origin is an owner - Factory patterns where the deploying contract is trusted
Initial Owner¶
Constructor requires a non-zero initial owner:
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(...);
}
_changeOwnership(initialOwner, true);
}
No Enumeration¶
Unlike some implementations, owners cannot be enumerated. You can only check if a specific address is an owner. This is a gas optimization trade-off.
Usage Pattern¶
contract MyContract is MultiOwnable {
constructor() MultiOwnable(msg.sender) {}
function adminFunction() public onlyOwners {
// Only owners can call this
}
function addAdmin(address newAdmin) public onlyOwners {
addOwner(newAdmin);
}
}
Security Considerations¶
- Any owner can add new owners
- Any owner can remove any owner (including themselves)
- No protection against removing all owners
- tx.origin check enables some use cases but has known security implications
- Consider carefully before using in high-security contexts
Compiled ABI¶
The compiled ABI below is produced by solc 0.8.21 from the exact source bytes hashed in the Contract Verification section. Consumers can paste it directly into ethers/web3/viem.
Click to expand JSON ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "origin",
"type": "address"
},
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "what",
"type": "address"
}
],
"name": "OwnableInvalidOwner",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "origin",
"type": "address"
},
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "address",
"name": "what",
"type": "address"
}
],
"name": "OwnableUnauthorizedAccount",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "bool",
"name": "state",
"type": "bool"
}
],
"name": "OwnershipUpdate",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "addOwner",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "cOwner",
"type": "address"
}
],
"name": "owner",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "toRemove",
"type": "address"
}
],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
Contract Verification¶
| Property | Value |
|---|---|
| Keccak256 Hash | 0xd5bc09d51ea952718d51fc0c347aad20278f6a1c7a0fda63e40ea9317fbd7720 |
| Source URL | https://raw.githubusercontent.com/busytoby/atropa_pulsechain/main/solidity/dysnomia/lib/multiownable.sol |
| Hash Generated | 2026-04-20T02:38:30Z |