//tips
//基本情報理解
IMAP internet message access protocloは、メールサーバ上の電子メールにアクセスして操作するためのプロトコルで、通信にSSL/TLSを組み合わせて暗号化する。
SMAP simple mail transfer protocolはメールサーバ間の転送と利用者からのメールの送信依頼を処理するという役割があり、メールの送信依頼処理をSMTP submissionといい、使用するポートもメール転送に用いる25番ではなく、587番ポートを利用する。メール送信者の認証を行い、暗号化にも対応する。
UML unified modeling languageのアクティビティ図はフローチャートのような一連の手続きを可視化できる図で、分岐やマージなどのほか、並行処理や例外処理が考慮されており、それらを表現できる。
アクティビティ図ではなく、配置図ではコンポーネントの物理的な関係が記述される。
//pitch deck
Cremaというロースターで引くこだわりコーヒーのサブスク販売企業のpitchを見つけた。数字での記載は少ないが、プレゼン内容は視覚的にも、文章的にもわかりやすく、コーヒーマーケットの変化、スーパー棚のブランドの固定化の解決策であること、そして運用の成長性からわかりやすくまとめられていた。ニッチだがコーヒー愛好家には刺さりそうな商品内容でマーケティングさえうまくできればある程度はグロースしそう。
数字が少なめのプレゼン資料としては、かなり高度なもののように思えたし、自分もサブスクしたいと思えたので、参考pitchとして記載。コーヒー愛好家としての補正が入っているかもしれない・・・。
//smartcontract
今回はexternalを学ぶ。NFTMarket is ownableの部分でエラーが出て困惑したがimportの方にはファイル名であるownableで、NFTMarket isの方にはコントラクト名であるOwnableを使う必要があった。
また、Kitty memory newKitty=Kitty(kitties.length,_name,address(0));の引数の順番はstruct Kittyの順番に書く必要がある。
NFTMarketコントラクトと先日まで作成していたbankコントラクトを連動させる。
NFTMarketでbuykittyを行う際に、bank側のコントラクトの資金移動を行わせるtransferを実行させる。つまり外部のコントラクトの内容を実行することになる。
外部コントラクトとのやりとりには、やりとりするアドレス情報だけでなく、関数の概要を示したinterfaceというものを導入する必要があるよう。
pragma solidity 0.8.4;
import './ownable.sol';
//interfaceでは使う外部の関数のヘッダーを記載する
interface Ibank{
function transferFrom(address _from, address _to, uint _amount) external;
function getBalance() external view returns(uint);
function withdraw(uint _amount) external;
}
contract NFTMarket is Ownable{
struct Kitty{
uint256 id;
string name;
address owner;
}
Kitty[] kitties;
mapping(address=>uint256[]) ownedKitties;
uint private price = 1000000000000000000;
//連動するbankコントラクトのアドレスを記録
address private bankAddr=0xd9145CCE52D386f254917e481eB44e9943F39138;//addressは""入らない
//Ibank(bankAddr)の略、変数化
Ibank bank =Ibank(bankAddr);
//コントラクトのデプロイ主しかcreateKittyは実行できない
function createKitty(string memory _name) external onlyOwner{
//名前を入れたらkittyをmint
//address(0)は0x000..00で誰のkittyでもないことを示す
Kitty memory newKitty=Kitty(kitties.length,_name,address(0));
kitties.push(newKitty);
}
//owner主を特定する関数
function getOwner()view external returns(address){
return owner;
}
function viewKitty()view external returns(Kitty[] memory){
return kitties;
}
function buyKitty(uint256 _id)external{
require(kitties[_id].owner == address(0),"not for sale");
ownedKitties[msg.sender].push(_id);
kitties[_id].owner=msg.sender;
//interfaceを上部で設定しているのでそちらを呼ぶ
//Ibank(bankAddr)でバンクコントラクトの関数にアクセスできるようになる
Ibank(bankAddr).transferFrom(msg.sender,address(this),price);
}
//Bankコントラクトからのお金の引き出し
function withdrawFromBank() external onlyOwner{
//外部からの受け取りなので上記にpayableを加えることができない
uint balance =bank.getBalance();
bank.withdraw(balance);
//ただこのままだとbankからのお金を受け取れないので
//別途receive関数が必要
}
//ownerに資金を輸送
function transferToOwner() external onlyOwner{
payable(msg.sender).transfer(address(this).balance);
}
//functionは不要
receive()external payable{
//中身は空欄で良い
//これによりbank.withdraw(balance);が機能する
}
}
下記はbankの方。
pragma solidity 0.8.4;
contract Bank {
event balanceUpdate(string indexed _txType, address indexed _owner, uint _amount);
mapping(address => uint) public balance;
//外部からのみ呼びたいためpublicからexternalに変更
function getBalance() external view returns(uint){
return balance[msg.sender];
}
function deposit() external payable {
balance[msg.sender] += msg.value;
emit balanceUpdate("Deposit", msg.sender, balance[msg.sender]);
}
function withdraw(uint _amount) external {
require(balance[msg.sender] >= _amount, "Insufficient balance");
balance[msg.sender] -= _amount;
payable(msg.sender).transfer(_amount);
emit balanceUpdate("Withdraw", msg.sender, balance[msg.sender]);
}
//interfaceにヘッダーを転載
function transferFrom(address _from, address _to, uint _amount) external {
//address _fromを追加して、どこから送るかの情報も引数に加えられるようにしている
require(balance[_from] >= _amount, "Insufficient balance");
require(_from != _to, "Invalid recipient");
balance[_from] -= _amount;
balance[_to] += _amount;
emit balanceUpdate("Outgoing Transfer", _from, balance[_from]);
emit balanceUpdate("Incoming Transfer", _to, balance[_to]);
}
}
Ownableは以前と変わらないので略するがだんだんボリューミーになってきた。