In PurposeHandler version 2.0, we learned to add permission control to functions via the require
statement.
Now we can add a real economy mechanism to it, so that the value of purpose
is controlled by a real bidding auction mechanism!
0x01 Add Owner
To get the owner of a contract owner
is a must-learn operation for newbies.
The easiest way is to set a public owner
variable and pass the _owner
parameter in the constructor.
pragma solidity >=0.8.0 <0.9.0;
//SPDX-License-Identifier: MIT
contract PurposeHandler {
string public purpose = "Building Unstoppable Apps";
address public owner = owner;
// fill in your own address (start with 0x) here
constructor(address _owner) {
owner = _owner;
}
function setPurpose(string memory newPurpose) public {
// about msg.sender:
// https://cryptozombies.io/en/lesson/2/chapter/3
// about require:
// https://cryptozombies.io/en/lesson/2/chapter/4
require( msg.sender == owner, "NOT THE OWNER!");
purpose = newPurpose;
console.log(msg.sender,"set purpose to",purpose);
}
}
In production, this is generally achieved by importing ownable.sol
.
ownable.sol
in OpenZepplin.
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol
ownable.sol
:
pragma solidity ^0.4.25;
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address private _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() internal {
_owner = msg.sender;
emit OwnershipTransferred(address(0), _owner);
}
/**
* @return the address of the owner.
*/
function owner() public view returns(address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner());
_;
}
/**
* @return true if `msg.sender` is the owner of the contract.
*/
function isOwner() public view returns(bool) {
return msg.sender == _owner;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
* @notice Renouncing to ownership will leave the contract without an owner.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0));
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
0x02 Create auction mechanism
by a require rule
The rule is that if the bid is higher than the current price, then the value of set-purpose
can be modified; if it is not as high as the current price, then an error is thrown.
pragma solidity >=0.8.0 <0.9.0;
//SPDX-License-Identifier: MIT
contract PurposeHandler {
string public purpose = "Building Unstoppable Apps";
address public owner = owner;
uint256 public price = 0.001 ether;
// fill in your own address (start with 0x) here
constructor(address _owner) {
owner = _owner;
}
function setPurpose(string memory newPurpose) payable public {
require( msg.value > price, "NOT ENOUGH!");
purpose = newPurpose;
// update price when guy set
price = msg.value;
console.log(msg.sender,"set purpose to",purpose);
}
}
0x03 Withdrawal mechanism
The function getBalance()
allows the owner
to get the balance in the contract, and the function getMyMoney
allows the balance in the contract to be withdrawn by.
pragma solidity >=0.8.0 <0.9.0;
//SPDX-License-Identifier: MIT
contract PurposeHandler {
string public purpose = "Building Unstoppable Apps";
address public owner;
uint256 public price = 0.001 ether;
constructor(address _owner) {
owner = _owner;
}
function setPurpose(string memory newPurpose) payable public {
require( msg.value > price, "NOT ENOUGH!");
purpose = newPurpose;
// update price when guy set
price = msg.value;
}
function getBalance() view public returns(uint256) {
return address(this).balance;
}
function getMyMoney(address _to, uint256 amount) public {
require(msg.sender==owner);
address payable receiver = payable(_to);
receiver.transfer(amount);
}
}
0x04 Record logs of set purpose by Event
What is an event?
A blockchain is a list of blocks - they are basically made up of transactions. Each transaction has a receipt attached to it, which contains zero or more log entries. These log entries represent the results generated when an event is triggered in a smart contract.
In Solidity source code, to define an
event
, you need to mark it by prefixing it with the event keyword (similar to the usage of thefunction
keyword). You can then call or trigger the event from within any function that you wish to generate the event. You can trigger events from any function using theemit
keyword.Someone may want to add "listen" for events in the DAPP. It uses the filtering functionality of Web 3.0 (filtering functionality of Web 3.0).
We can add event
to the setPurpose function to record the history of set purpose.
Translated with www.DeepL.com/Translator (free version)
pragma solidity >=0.8.0 <0.9.0;
//SPDX-License-Identifier: MIT
contract PurposeHandler {
event SetPurpose(address sender, string purpose);
string public purpose = "Building Unstoppable Apps";
address public owner;
uint256 public price = 0.001 ether;
constructor(address _owner) {
owner = _owner;
}
function setPurpose(string memory newPurpose) payable public {
require( msg.value > price, "NOT ENOUGH!");
purpose = newPurpose;
// update price when guy set
price = msg.value;
emit SetPurpose(msg.sender, purpose);
}
function getBalance() view public returns(uint256) {
return address(this).balance;
}
function getMyMoney(address _to, uint256 amount) public {
require(msg.sender==owner);
address payable receiver = payable(_to);
receiver.transfer(amount);
}
}
Summary
That's it for Get & Set value series. Here are all the articles for Get & Set value series.
In the next post, we move on to the next chapter - the design and implementation of the NFT dApp!
Authors: