Applying common smart contract design patterns
Restrict function access to authorized users only
contract AccessControl {
address public owner;
mapping(address => bool) public admins;
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
modifier onlyAdmin() {
require(admins[msg.sender], "Not admin");
_;
}
function addAdmin(address _admin) public onlyOwner {
admins[_admin] = true;
}
}
Emergency stop mechanism for critical situations
bool public stopped = false;
modifier stopInEmergency() {
require(!stopped, "Contract is stopped");
_;
}
function emergencyStop() public onlyOwner {
stopped = true;
}
mapping(address => uint) pendingWithdrawals;
function withdraw() public {
uint amount = pendingWithdrawals[msg.sender];
pendingWithdrawals[msg.sender] = 0;
payable(msg.sender).transfer(amount);
}
mapping(address => uint) lastWithdrawal;
uint constant COOLDOWN = 1 days;
modifier rateLimited() {
require(block.timestamp >=
lastWithdrawal[msg.sender] + COOLDOWN);
lastWithdrawal[msg.sender] = block.timestamp;
_;
}
enum State { Created, Locked, Released, Inactive }
State public state;
modifier inState(State _state) {
require(state == _state, "Invalid state");
_;
}
modifier transitionTo(State _state) {
_;
state = _state;
}
function lock() public inState(State.Created) transitionTo(State.Locked) {
// Lock logic
}
Visualize how patterns change behavior. Choose a pattern and press Play to see how messages, state and funds move across components.
Next, we'll explore DLT-based Smart Contracts across different platforms.