Este documento describe la comunicación multimedia en el navegador a través de WebRTC y cómo puede interactuar con SIP. WebRTC permite llamadas de voz y video directamente en el navegador sin plugins. SIP puede usarse como protocolo de señalización con WebRTC a través de WebSocket. JsSIP implementa SIP en JavaScript para aplicaciones web, permitiendo que los navegadores se comuniquen con dispositivos SIP existentes a través de un proxy SIP como OverSIP.
오랜 기간 우리의 인프라를 괴롭혀온 DDoS 공격은 방어 기법의 발전에도 불구하고 나름의 진화 과정을 거치며 생존했습니다. DDoS 공격은 다양한 유형의 공격 기법과 회선 초과의 조합 때문에 막기가 쉽지 않으며, 효과적인 대응을 위해서는 보안 장비 외에 인프라 차원에서의 대응과 전환 절차가 필요합니다.
공격과 방어의 트렌드를 짚어보고, 알려진 방법들의 한계점을 분석하며, 기술적/전략적 관점에서의 대응 방법을 공유합니다.
목차
1. DDoS?
2. 진화와 공방
3. 진압 기법들과 딜레마
4. 대응 절차와 준비물
대상
시스템/네트워크/보안 인프라를 담당하는 인프라 전문가 또는 관련 개발자
StarkNet is a permissionless ZK-Rollup layer 2 scaling solution for Ethereum that enables massive scalability without compromising security. It uses Cairo, a new programming language with some quirks compared to Solidity like using mappings instead of arrays and special assertions instead of boolean expressions. A basic dApp could include stake contracts on both StarkNet (L2) and Ethereum (L1) along with functions for depositing, withdrawing, and transferring fees between layers using StarkNet's ability to pass messages between L1 and L2 contracts. The dApp contracts would need to be compiled and deployed to both StarkNet and Ethereum.
Blazor is open source SPA framework from Microsoft
Overview
What is Blazor? Why do need Blazor
Overview of Blazor Hosting Model, Components , Bindings , Parameters
Dependency Injection
JS Interoperability
Demos
Wrap up
Q&A
Este documento describe la comunicación multimedia en el navegador a través de WebRTC y cómo puede interactuar con SIP. WebRTC permite llamadas de voz y video directamente en el navegador sin plugins. SIP puede usarse como protocolo de señalización con WebRTC a través de WebSocket. JsSIP implementa SIP en JavaScript para aplicaciones web, permitiendo que los navegadores se comuniquen con dispositivos SIP existentes a través de un proxy SIP como OverSIP.
오랜 기간 우리의 인프라를 괴롭혀온 DDoS 공격은 방어 기법의 발전에도 불구하고 나름의 진화 과정을 거치며 생존했습니다. DDoS 공격은 다양한 유형의 공격 기법과 회선 초과의 조합 때문에 막기가 쉽지 않으며, 효과적인 대응을 위해서는 보안 장비 외에 인프라 차원에서의 대응과 전환 절차가 필요합니다.
공격과 방어의 트렌드를 짚어보고, 알려진 방법들의 한계점을 분석하며, 기술적/전략적 관점에서의 대응 방법을 공유합니다.
목차
1. DDoS?
2. 진화와 공방
3. 진압 기법들과 딜레마
4. 대응 절차와 준비물
대상
시스템/네트워크/보안 인프라를 담당하는 인프라 전문가 또는 관련 개발자
StarkNet is a permissionless ZK-Rollup layer 2 scaling solution for Ethereum that enables massive scalability without compromising security. It uses Cairo, a new programming language with some quirks compared to Solidity like using mappings instead of arrays and special assertions instead of boolean expressions. A basic dApp could include stake contracts on both StarkNet (L2) and Ethereum (L1) along with functions for depositing, withdrawing, and transferring fees between layers using StarkNet's ability to pass messages between L1 and L2 contracts. The dApp contracts would need to be compiled and deployed to both StarkNet and Ethereum.
Blazor is open source SPA framework from Microsoft
Overview
What is Blazor? Why do need Blazor
Overview of Blazor Hosting Model, Components , Bindings , Parameters
Dependency Injection
JS Interoperability
Demos
Wrap up
Q&A
This document summarizes a presentation about using Stitches, a React styling library, and Storybook for component design.
The presentation introduces Stitches as the styling library used for its support of React, easy usage, and themes. Key features of Stitches discussed include creating styled components, variants, and comparisons to other libraries.
Storybook is presented as a way to improve communication between designers and developers by allowing visualization of components alongside their stories. Clean communication through a shared Storybook is emphasized.
Reflections on initially creating a design system note the benefits of consistency and speed but also identify areas for improvement like documentation, process alignment, and understanding each other's roles. Establishing trust and understanding between
Active Directory is a directory service that provides a centralized location to store information about networked devices, services, and users. It implements authentication, authorization, and other services to securely manage access and share information across a network. Active Directory uses a hierarchical structure and replication to distribute directory data and updates between domain controllers, providing scalability and redundancy. It supports LDAP for application access and integrates with DNS for network name resolution.
This document provides a summary of a masterclass on building distributed real-time systems using the Data Distribution Service (DDS). The class covers DDS concepts and technology, including runtime services, development tools, and standards. It discusses how DDS enables a data-centric model and global data space to support high-performance, scalable, and reliable real-time systems that interact directly with the physical world.
Anonymous credentials with range proofs, verifiable encryption, ZKSNARKs, Cir...SSIMeetup
Lovesh Harchandani from Dock presents their approach to anonymous credentials and dives in on the various predicates that can be proven in zero knowledge. In over 90 minutes of discussion, we cover what these cryptographic techniques are, how they enable several important use cases for digital identity credentials, and we stretch James Monaghan's ability to keep up as interviewer by taking a look at the source code which makes it all possible! We show how various zero knowledge primitives we've built can be used in a modular fashion to solve real-world use cases. We cover privacy-preserving signature schemes, zero knowledge attribute equalities, range proofs, and verifiable encryption based on ZK-SNARKs, expressing arbitrary predicates as Circom programs and creating ZK proofs for them and blinded credentials (issuer is unaware of all attributes). For anyone interested in the technical underpinnings of this new frontier of digital identity, this episode is a must!
OpenID for Verifiable Credentials is a family of protocols supporting implementation of applications with Verifiable Credentials, i.e. verifiable credential issuance, credential presentation, and pseudonyms authentication.
This document provides an overview of a Microsoft course module on managing Active Directory Domain Services objects. The module includes lessons on managing user accounts, groups, computer accounts, and delegating administration. It demonstrates how to perform tasks like creating users and groups, managing computer objects, and delegating administrative permissions to organizational units. The goal is to prepare students to configure Active Directory infrastructure for a new branch office by creating and managing required objects and delegating permissions.
This document discusses using xAPI to track learning experiences in Unity projects. It begins with an introduction of the presenter and overview of the agenda. The presenter then discusses why xAPI should be added to Unity games for learning via augmented/virtual reality. Two libraries for adding xAPI to Unity projects are described: TinCan.Net and GBLxAPI. Both have pros and cons, but using both allows getting the advantages of both. Resources for further information are provided.
Hot Topics: The DuraSpace Community Webinar Series,
“Introducing DSpace 7: Next Generation UI”
Curated by Claire Knowles, Library Digital Development Manager, The University of Edinburgh.
Introducing DSpace 7
February 28, 2017 presented by: Claire Knowles - The University of Edinburgh, Art Lowel - Atmire, Andrea Bollini - 4Science, Tim Donohue – DuraSpace
This document provides information about MongoDB and its suitability for e-commerce applications. It discusses how MongoDB allows for a flexible schema that can accommodate different product types like books, music albums, jeans, without needing to define all attributes in advance. This flexibility addresses the "data dilemma" that traditional relational databases have in modeling diverse e-commerce data. Examples of companies successfully using MongoDB for e-commerce are also provided.
OpenID Connect 4 SSI aims at specifying a set of protocols based on OpenID Connect to enable SSI applications. The initiative is conducted at OpenID Foundation in liaison with the Decentralized Identity Foundation (DIF). One of the specifications is built up on DID-SIOP in DIDAuth WG in DIF and SIOP v1 in OIDC Core.
Ihre HCL Nomad Konfiguration immer & ueberall griffbereit-MarvelClient Roamin...panagenda
Webinar Recording: https://www.panagenda.com/webinars/ihre-hcl-nomad-konfiguration-immer-und-ueberall-griffbereit-marvelclient-roaming-ist-da/
HCL Nomad ist ein moderner Client, bei dem die Benutzer ein modernes Anwendungserlebnis erwarten. Aber ständiges Suchen nach Anwendungen oder Konfigurieren von Einstellungen ist aus Nutzersicht schlichtweg nicht mehr zeitgemäß. Optimal ist, wenn alles auf dem gleichen Stand ist – egal auf welchem Gerät man arbeitet.
Alltägliche Szenarien im Umgang mit mobilen Geräten und Browsern erweisen sich leider immer noch als Alptraum. Um Probleme zu beheben, wird Nomad auf Handys und Tablets immer wieder gelöscht und neu installiert. Menschen verlieren ihre Geräte und bekommen neue. In Browsern ist es sogar noch schlimmer, weil es keine sichtbare App gibt; sie ist nur tief im Cache versteckt. Wenn man den Cache zurücksetzt oder Nomad in einem neuen Browser öffnet, sieht man wieder eine weiße Fläche. BYOD vervielfacht diese Probleme nur.
Sie wissen das, und Sie verstehen, dass die Konfiguration von HCL Nomad eine knifflige Angelegenheit sein kann. Aber Benutzer erwarten heutzutage einfach, dass Nomad sich wie jede andere moderne Anwendung verhält. Und es ist sehr wahrscheinlich, dass die Benutzer der IT die Schuld geben, wenn dies nicht der Fall ist.
NEU: MarvelClient Roaming stellt jetzt automatisch sicher, dass Ihre HCL Nomad-Konfiguration über alle Ihre Geräte hinweg zugänglich ist. Es ermöglicht die automatische Sicherung, Wiederherstellung und gemeinsame Nutzung von Konfigurationen zwischen Geräten, die Nomad nutzen (Desktop, aktuelle Anwendungen, Einstellungen und mehr). Es lädt die Konfigurationen auf Ihre Domino-Server hoch, sobald sie geändert werden, und aktualisiert dann transparent alle aktuellen und neuen Geräte, die von derselben Person verwendet werden, mit einem winzigen Netzwerk- und Verarbeitungs-Overhead. Alle Ihre Geräte – ein nahtloses Erlebnis.
Nehmen Sie an diesem Webinar am 10. November teil und erfahren Sie, wie Sie mit MarvelClient Roaming eine moderne, beständige Benutzererfahrung für HCL Nomad bereitstellen können – überall und jederzeit.
Dabei gehen wir besonders auf die folgenden Themen ein:
- Wie die Benutzererfahrung von HCL Nomad mittels MarvelClient Roaming verbessert werden kann
- Wie einfach Sie HCL Nomad-Konfigurationen für alle Ihre Geräte einrichten können
- Best Practices, die Ihnen (und Ihren Benutzern) das Leben leichter machen
- Entdecken Sie mehrere MarvelClient Roaming Tools für eine dauerhafte, moderne Benutzererfahrung
This document summarizes a presentation about using Stitches, a React styling library, and Storybook for component design.
The presentation introduces Stitches as the styling library used for its support of React, easy usage, and themes. Key features of Stitches discussed include creating styled components, variants, and comparisons to other libraries.
Storybook is presented as a way to improve communication between designers and developers by allowing visualization of components alongside their stories. Clean communication through a shared Storybook is emphasized.
Reflections on initially creating a design system note the benefits of consistency and speed but also identify areas for improvement like documentation, process alignment, and understanding each other's roles. Establishing trust and understanding between
Active Directory is a directory service that provides a centralized location to store information about networked devices, services, and users. It implements authentication, authorization, and other services to securely manage access and share information across a network. Active Directory uses a hierarchical structure and replication to distribute directory data and updates between domain controllers, providing scalability and redundancy. It supports LDAP for application access and integrates with DNS for network name resolution.
This document provides a summary of a masterclass on building distributed real-time systems using the Data Distribution Service (DDS). The class covers DDS concepts and technology, including runtime services, development tools, and standards. It discusses how DDS enables a data-centric model and global data space to support high-performance, scalable, and reliable real-time systems that interact directly with the physical world.
Anonymous credentials with range proofs, verifiable encryption, ZKSNARKs, Cir...SSIMeetup
Lovesh Harchandani from Dock presents their approach to anonymous credentials and dives in on the various predicates that can be proven in zero knowledge. In over 90 minutes of discussion, we cover what these cryptographic techniques are, how they enable several important use cases for digital identity credentials, and we stretch James Monaghan's ability to keep up as interviewer by taking a look at the source code which makes it all possible! We show how various zero knowledge primitives we've built can be used in a modular fashion to solve real-world use cases. We cover privacy-preserving signature schemes, zero knowledge attribute equalities, range proofs, and verifiable encryption based on ZK-SNARKs, expressing arbitrary predicates as Circom programs and creating ZK proofs for them and blinded credentials (issuer is unaware of all attributes). For anyone interested in the technical underpinnings of this new frontier of digital identity, this episode is a must!
OpenID for Verifiable Credentials is a family of protocols supporting implementation of applications with Verifiable Credentials, i.e. verifiable credential issuance, credential presentation, and pseudonyms authentication.
This document provides an overview of a Microsoft course module on managing Active Directory Domain Services objects. The module includes lessons on managing user accounts, groups, computer accounts, and delegating administration. It demonstrates how to perform tasks like creating users and groups, managing computer objects, and delegating administrative permissions to organizational units. The goal is to prepare students to configure Active Directory infrastructure for a new branch office by creating and managing required objects and delegating permissions.
This document discusses using xAPI to track learning experiences in Unity projects. It begins with an introduction of the presenter and overview of the agenda. The presenter then discusses why xAPI should be added to Unity games for learning via augmented/virtual reality. Two libraries for adding xAPI to Unity projects are described: TinCan.Net and GBLxAPI. Both have pros and cons, but using both allows getting the advantages of both. Resources for further information are provided.
Hot Topics: The DuraSpace Community Webinar Series,
“Introducing DSpace 7: Next Generation UI”
Curated by Claire Knowles, Library Digital Development Manager, The University of Edinburgh.
Introducing DSpace 7
February 28, 2017 presented by: Claire Knowles - The University of Edinburgh, Art Lowel - Atmire, Andrea Bollini - 4Science, Tim Donohue – DuraSpace
This document provides information about MongoDB and its suitability for e-commerce applications. It discusses how MongoDB allows for a flexible schema that can accommodate different product types like books, music albums, jeans, without needing to define all attributes in advance. This flexibility addresses the "data dilemma" that traditional relational databases have in modeling diverse e-commerce data. Examples of companies successfully using MongoDB for e-commerce are also provided.
OpenID Connect 4 SSI aims at specifying a set of protocols based on OpenID Connect to enable SSI applications. The initiative is conducted at OpenID Foundation in liaison with the Decentralized Identity Foundation (DIF). One of the specifications is built up on DID-SIOP in DIDAuth WG in DIF and SIOP v1 in OIDC Core.
Ihre HCL Nomad Konfiguration immer & ueberall griffbereit-MarvelClient Roamin...panagenda
Webinar Recording: https://www.panagenda.com/webinars/ihre-hcl-nomad-konfiguration-immer-und-ueberall-griffbereit-marvelclient-roaming-ist-da/
HCL Nomad ist ein moderner Client, bei dem die Benutzer ein modernes Anwendungserlebnis erwarten. Aber ständiges Suchen nach Anwendungen oder Konfigurieren von Einstellungen ist aus Nutzersicht schlichtweg nicht mehr zeitgemäß. Optimal ist, wenn alles auf dem gleichen Stand ist – egal auf welchem Gerät man arbeitet.
Alltägliche Szenarien im Umgang mit mobilen Geräten und Browsern erweisen sich leider immer noch als Alptraum. Um Probleme zu beheben, wird Nomad auf Handys und Tablets immer wieder gelöscht und neu installiert. Menschen verlieren ihre Geräte und bekommen neue. In Browsern ist es sogar noch schlimmer, weil es keine sichtbare App gibt; sie ist nur tief im Cache versteckt. Wenn man den Cache zurücksetzt oder Nomad in einem neuen Browser öffnet, sieht man wieder eine weiße Fläche. BYOD vervielfacht diese Probleme nur.
Sie wissen das, und Sie verstehen, dass die Konfiguration von HCL Nomad eine knifflige Angelegenheit sein kann. Aber Benutzer erwarten heutzutage einfach, dass Nomad sich wie jede andere moderne Anwendung verhält. Und es ist sehr wahrscheinlich, dass die Benutzer der IT die Schuld geben, wenn dies nicht der Fall ist.
NEU: MarvelClient Roaming stellt jetzt automatisch sicher, dass Ihre HCL Nomad-Konfiguration über alle Ihre Geräte hinweg zugänglich ist. Es ermöglicht die automatische Sicherung, Wiederherstellung und gemeinsame Nutzung von Konfigurationen zwischen Geräten, die Nomad nutzen (Desktop, aktuelle Anwendungen, Einstellungen und mehr). Es lädt die Konfigurationen auf Ihre Domino-Server hoch, sobald sie geändert werden, und aktualisiert dann transparent alle aktuellen und neuen Geräte, die von derselben Person verwendet werden, mit einem winzigen Netzwerk- und Verarbeitungs-Overhead. Alle Ihre Geräte – ein nahtloses Erlebnis.
Nehmen Sie an diesem Webinar am 10. November teil und erfahren Sie, wie Sie mit MarvelClient Roaming eine moderne, beständige Benutzererfahrung für HCL Nomad bereitstellen können – überall und jederzeit.
Dabei gehen wir besonders auf die folgenden Themen ein:
- Wie die Benutzererfahrung von HCL Nomad mittels MarvelClient Roaming verbessert werden kann
- Wie einfach Sie HCL Nomad-Konfigurationen für alle Ihre Geräte einrichten können
- Best Practices, die Ihnen (und Ihren Benutzern) das Leben leichter machen
- Entdecken Sie mehrere MarvelClient Roaming Tools für eine dauerhafte, moderne Benutzererfahrung
1. ERC721 Token & CryptoKitties
분석
Editor: SooBokJin
Email: thdnthdn24@gmail.com
2. 목차
1. ERC721 definition
2. ERC721 standard
3. ERC721 Implementation - openzeppelin ERC721Token
3.1. contract 상속 관계
3.2. 변수 분석
1) ERC721BasicToken
2) ERC721Token
3.3. 주요 동작에 따른 메서드 분석
1) 토큰 생성 (create token)
2) 토큰 전달 (transfer token)
3) 권한 부여 (approve token)
4) 토큰 삭제 (burn token)
3. 목차
4. ERC721 example – cryptokitties
4.1 cryptokitties
1) intro
2) Kitty property
4.2 크립토키티에서 ERC721이 어떻게 쓰였나?
1) 시작에 앞서
2) 주요 변수
3) flow
4.3 크립토키티 주요 메서드 분석
1) breed
2) birth
3) transfer
4) approve
5. 1. ERC721 definition
ERC-721 is a free, open standard that describes how to build non-fungible or unique tokens on the
Ethereum blockchain. While most tokens are fungible (every token is the same as every other token),
ERC-721 tokens are all unique.
6. interface ERC721 /* is ERC165 */ {
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
function approve(address _approved, uint256 _tokenId) external payable;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
interface ERC165 {
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
eip-ERC721 standard
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
2. ERC721 standard
8. ERC721 코드를 분석하기 앞서 토큰의 핵심 동작을 이해할 필요가 있다.
1. Ownership
How is token ownership handled?
2. Creation
How are tokens created?
3. Transfer & Allowance
How are tokens transferred, and how do we allow other addresses (contracts or externally owned accounts)
transfer capability?
4. Burn
How do we burn or destroy a token?
3. ERC721 Implementation - intro
10. 3.2. 변수 분석 - ERC721BasicToken
mapping (uint256 => address) internal tokenOwner
각 토큰(tokenId)의 소유주(address)를 기록하는 변수
mapping (address => uint256) internal ownedTokensCount
각 address 별 총 token 보유 개수를 기록하는 변수
mapping (uint256 => address) internal tokenApprovals
토큰(tokenId)에 대한 사용 권한을 얻은(approved) address를 기록하는 변수
mapping (address => mapping (address => bool)) internal operatorApprovals
특정 address에게 자신이 보유한 모든 token(ownedTokens)에 대한 사용 권한을 부여(approve)했는지에 대한 여부를 기록하는 변수. default는 0(false)이다.
tokenId 1
tokenId 2
tokenId 3
…
addr 1(0x24da..)
addr 2(0x32fe.. )
addr 3(0x52de..)
…
addr 1(0x24da..)
addr 2(0x32fe.. )
addr 3(0x52de..)
…
6
2
3
…
tokenId 1
tokenId 2
tokenId 3
…
approved addr 1(0x24da..)
approved addr 2(0x32fe.. )
approved addr 3(0x52de..)
…
각 address가 보유한 token 개수
addr 1(0x24da..)
addr 2(0x32fe.. )
addr 3(0x52de..)
…
approvalForAll addr 1(0x39qe.. )
approvalForAll addr 2(0x10yv.. )
approvalForAll addr 3(0x92dw..)
…
true
false
true
…
true: approvalForAll addr x는 addr1 이 보유한 모든 토큰(ownedTokens)에 대한 사용 권한을 지님
false: default 값, approvalForAll addr x는addr1이 보유한 토큰에 대한 사용 권한이 없음
11. 3.2. 변수 분석 - ERC721Token
string internal name_
token name(e.g. CryptoKitties)
string internal symbol_
token symbol(e.g. CK)
mapping(uint256 => uint256) internal ownedTokensIndex
토큰(tokenId)과 ownedTokens의 value값의 index를 mapping
mapping(address => uint256[]) internal ownedTokens
각 address가 소유한 모든 token을 배열 형태로 기록하는 변수
uint256[] internal allTokens
모든 토큰(tokenId)을 배열의 형태로 기록한 변수
mapping(uint256 => uint256) internal allTokensIndex
tokenId와 allTokens 배열의 index를 mapping
mapping(uint256 => string) internal tokenURIs
Optional mapping for token URIs(분석 필요)
addr 1(0x24da..)
addr 2(0x32fe.. )
addr 3(0x52de..)
…
0
1
2
tokenId 1
tokenId 2
tokenId 3
…
tokenId 1
tokenId 2
tokenId 3
…
0
7
3
…
ownedTokens의 index(값 중복 존재)
0
1
2
tokenId 1
tokenId 2
tokenId 3
…
0
1
2
tokenId 1
tokenId 2
tokenId 3
…
0
1
2
…
allTokens의 index
12. 3.2. 핵심 변수
mapping (uint256 => address) internal tokenOwner
각 토큰(tokenId)의 소유주(address)를 기록하는 변수
tokenId 1
tokenId 2
tokenId 3
…
addr 1(0x24da..)
addr 2(0x32fe.. )
addr 3(0x52de..)
…
mapping(address => uint256[]) internal ownedTokens
각 address가 소유한 모든 token을 배열 형태로 기록하는 변수
addr 1(0x24da..)
addr 2(0x32fe.. )
addr 3(0x52de..)
…
0
1
2
tokenId 1
tokenId 2
tokenId 3
…
uint256[] internal allTokens
모든 토큰(tokenId)을 배열의 형태로 기록한 변수
0
1
2
tokenId 1
tokenId 2
tokenId 3
…
mapping (uint256 => address) internal tokenApprovals
토큰(tokenId)에 대한 사용 권한을 얻은(approved) address를 기록하는 변수
tokenId 1
tokenId 2
tokenId 3
…
approved addr 1(0x24da..)
approved addr 2(0x32fe.. )
approved addr 3(0x52de..)
…
토큰별 소유주 address 정보
각 address가 소유한 모든 토큰 정보
현재까지 생성된 모든 토큰 정보
토큰의 사용 권한을 얻은 address 정보
13. 3.3. 주요 동작에 따른 메서드 분석 - view function
function balanceOf(address _owner) public view returns (uint256) {
require(_owner != address(0));
return ownedTokensCount[_owner];
}
function ownerOf(uint256 _tokenId) public view returns (address) {
address owner = tokenOwner[_tokenId];
require(owner != address(0));
return owner;
}
function exists(uint256 _tokenId) public view returns (bool) {
address owner = tokenOwner[_tokenId];
return owner != address(0);
}
function name() external view returns (string) {
return name_;
}
function symbol() external view returns (string) {
return symbol_;
}
function tokenURI(uint256 _tokenId) public view returns (string) {
require(exists(_tokenId));
return tokenURIs[_tokenId];
}
function tokenOfOwnerByIndex(address _owner, uint256 _index) public view returns (uint256)
{
require(_index < balanceOf(_owner));
return ownedTokens[_owner][_index];
}
function totalSupply() public view returns (uint256) {
return allTokens.length;
}
function tokenByIndex(uint256 _index) public view returns (uint256) {
require(_index < totalSupply());
return allTokens[_index];
}
ERC721Token.solERC721BasicToken.sol
14. 3.3. 주요 동작에 따른 메서드 분석 - create token
function _mint(address _to, uint256 _tokenId) internal {
super._mint(_to, _tokenId);
allTokensIndex[_tokenId] = allTokens.length;
allTokens.push(_tokenId);
}
function _mint(address _to, uint256 _tokenId) internal {
require(_to != address(0));
addTokenTo(_to, _tokenId);
emit Transfer(address(0), _to, _tokenId);
}
function addTokenTo(address _to, uint256 _tokenId) internal {
super.addTokenTo(_to, _tokenId);
uint256 length = ownedTokens[_to].length;
ownedTokens[_to].push(_tokenId);
ownedTokensIndex[_tokenId] = length;
}
function addTokenTo(address _to, uint256 _tokenId) internal {
require(tokenOwner[_tokenId] == address(0));
tokenOwner[_tokenId] = _to;
ownedTokensCount[_to] = ownedTokensCount[_to].add(1);
}
ERC721Token.sol ERC721BasicToken.sol
ERC721Token.sol
ERC721BasicToken.sol
1 2
3
4
internal이므로 contract 외부에서 메서드 호출 불가
(public으로 설정할 경우 누구든지 특정 tokenId를 생성할 수 있게 됨)
_mint는 ERC721 standard method가 아니다
(openzeppelin에서 구현)
15. 3.3. 주요 동작에 따른 메서드 분석 - create token
메서드(method)
_mint(address _to, uint256 _tokenId)
매개변수(parameter)
_to: 새로 생성될 토큰의 소유주(address)
_tokenId: 새로 생성될 토큰의 고유값(uint256)
동작 흐름 설명
토큰(tokenId)의 소유주(address)를 기록하는 변수인 tokenOwner에 값을 기록하고(tokenOwner[_tokenId] = _to) 동시에 소유주의 토큰 보유량을 기록하는 변수인
ownedTokensCount의 값을 1 증가 시킨다(ownedTokensCount[_to] = ownedTokensCount[_to].add(1)).
※ 새로 생성된 토큰에 대한 소유주가 이미 존재하면(이미 존재하는 tokenId이면) revert된다(require(tokenOwner[_tokenId] == address(0)).
이후 토큰 소유주가 보유한 모든 토큰을 배열의 형태로 기록하는 ownedTokens에 새로 생성된 토큰(_tokenId)을 추가한다(ownedTokens[_to].push(_tokenId)).
이 때 ownedTokens의 value인 tokenId 배열의 index값을 기록하는 ownedTokenIndex 변수에 새로 생성된 토큰의 index값을추가한다
(ownedTokensIndex[_tokenId] = length).
마지막으로 allTokens에 새로 생성된 토큰을 등록한다(allTokens.push(_tokenId)). 동시에 allTokensIndex도 등록한다(allTokensIndex[_tokenId] = allTokens.length).
※ _mint 메서드는 internal이므로 외부에서 직접 호출이 불가하며, 해당 함수를 호출하는 메서드를 추가 구현해야한다. 이때 _mint를 호출하는 메서드(호출자)에서
_mint 메서드 호출 권한을 유동적으로 설정할 수 있을 것으로 예상된다(체크 필요).
실행 후 변경되는 변수
tokenOwner: tokenOwner[_tokenId] = _to
ownedTokensCount: ownedTokensCount[_to]++
ownedTokens: ownedTokens[_to]에 mapping되는 token array에 _tokenId 기록
ownedTokensIndex: ownedTokens[_to] mapping되는 token array에 추가된 _tokenId의 index 기록
allTokens: 새로 생성된 _tokenId 기록
allTokensIndex: allTokens에 추가된 _tokenId의 index 기록
18. 3.3. 주요 동작에 따른 메서드 분석 - transfer token
메서드(method)
transferFrom(address _from, address _to, uint256 _tokenId)
매개변수(parameter)
_from: 현재 토큰(_tokenId)의 소유주 주소(address),
_to: 토큰을 받는 주소(address)
_tokenId: 전송할 토큰Id(uint256)
동작 흐름 설명
우선 메서드를 실행시킨 주체(호출자, msg.sender)가 해당 토큰에 대한 사용권한을 가지고 있는 지 체크한다(canTransfer). 1) 토큰 소유주이거나(tokenOwner), 2) 소
유주로부터 권한을 받았거나(getApproved), 3) 해당 토큰 소유주의 모든 토큰에 대한 사용 권한을 가지고 있는 경우(isApprovedForAll) 다음 처리가 진행된다.
권한 확인한 후 해당 토큰(_tokenId)에 대한 사용 권한을 가진 address를 기록하는 tokenApprovals의 값을 0x000.. 으로 초기화한다
(clearApproval(_from, _tokenId)).
이후 토큰의 소유주(_to)를 기록하는 변수인 tokenOwner의 값을 0x00... 으로 초기화한다(tokenOwner[_tokenId] = address(0)). 토큰의 소유주가 변경되었다는 말은
이전 소유주(_from)가 보유한 토큰 개수가 한 개 줄어들었음을 의미하므로 ownedTokensCount의 값에서 1을 뺸다
(ownedTokensCount[_from] = ownedTokensCount[_from].sub(1)).
ownedTokens[_from]에 mapping되는 token array에서 거래되는 토큰(_tokenId)을 제거한다. 이때 배열의 길이를 효율적으로 관리하기 위한 reorg 작업이 진행된다.
※ reorg의 핵심 원리는 token array의 마지막 요소를 제거되는 토큰의 위치에 넣어주고 token array의 길이를 -1 하는 방식이다.
※ 이더리움의 경우 배열의 특정 요소를 삭제한다는 것은 요소 배열에서 빠지는 것이 아니라 해당 요소의 값이 0으로 초기화됨을 의미한다(e.g. [1,2,3]에서 0번째 값(1)
을 삭제하면 [0,2,3]이 된다.).
solidity의 length: Arrays have a length member to hold their number of elements. Dynamic arrays can be resized in storage (not in memory) by changing
the .length member.
참고: http://solidity.readthedocs.io/en/v0.4.24/types.html
마지막으로 토큰을 전달받는 address의 정보를 업데이트한다. 해당 작업은 token creation에서 호출된 addTokenTo 메서드를 이용한다.
19. 3.3. 주요 동작에 따른 메서드 분석 - transfer token
실행 후 변경되는 변수
tokenOwner: tokenOwner[_tokenId] = _to
ownedTokensCount: ownedTokensCount[_from]-- , ownedTokensCount[_to]++
ownedTokens:
- ownedTokens[_from]: 배열에서 _tokenId 요소 제거(해당 자리에 배열의 마지막 요소 tokenId가 들어가고 length--)
- ownedTokens[_to]: 배열에 _tokenId 추가, length++
ownedTokensIndex:
- ownedTokensIndex[_tokenId]: ownedTokens[_to]에 mapping되는 array의 마지막 요소 index
- ownedTokensIndex[lastToken]: ownedTokens[_from]에 mapping되는 array의 이전에 _tokenId가 위치했던 index
21. function approve(address _to, uint256 _tokenId) public {
address owner = ownerOf(_tokenId);
require(_to != owner);
require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
tokenApprovals[_tokenId] = _to;
emit Approval(owner, _to, _tokenId);
}
function getApproved(uint256 _tokenId) public view returns (address) {
return tokenApprovals[_tokenId];
}
function isApprovedForAll(address _owner, address _operator) public view returns (bool)
{
return operatorApprovals[_owner][_operator];
}
function setApprovalForAll(address _to, bool _approved) public {
require(_to != msg.sender);
operatorApprovals[msg.sender][_to] = _approved;
emit ApprovalForAll(msg.sender, _to, _approved);
}
3.3. 주요 동작에 따른 메서드 분석 - approve token
ERC721BasicToken.sol ERC721BasicToken.sol
ERC721BasicToken.sol
ERC721BasicToken.sol
setApprovalForAll() function을 통해 setting
getApproved() function을 통해 approve 확인
1 2
22. 3.3. 주요 동작에 따른 메서드 분석 - approve token
메서드(method)
approve(address _to, uint256 _tokenId)
매개변수(parameter)
_to: 새로 생성될 토큰의 소유주(address)
_tokenId:
동작 흐름 설명
아래의 조건 중 하나를 만족하는 경우에만 tokenId에 대한 사용 권한을 특정 address에게 부여할 수 있다.
1) tokenOwner
address가 토큰의 실 소유주인 경우(tokenOwner[tokenId] == address)
2) operatorApprovals
address가 실 소유주(owner)로부터 모든 토큰에 대한 권한을 부여받은 경우
(operatorApproval[owner][address] == true)
approve 메서드에서는 인수로 받은 address(_to)가 위 조건을 만족하는 지 확인한 후, 인수로 받은 토큰(_tokenId)에 대한 권한을 _to에게 부여한다
(tokenApprovals[_tokenId] = _to).
실행 후 변경되는 변수
tokenApprovals: tokenApprovals[_tokenId] = _to
24. 3.3. 주요 동작에 따른 메서드 분석 - burn token
메서드(method)
_burn(address _owner, uint256 _tokenId)
매개변수(parameter)
_owner: 제거될 토큰(_tokenId)의 소유주(address)
_tokenId: 제거되는 토큰
동작 흐름 설명
transferFrom메서드 내부에서 사용된 clearApproval, removeTokenFrom 메서드를 통해 tokenOwner 초기화(0x00..) 및 ownedTokens에 기록된 토큰 정보를 제거한다.
이후 모든 토큰에 대한 정보를 기록하는 allTokens에 해당 토큰(_tokenId)에 대한 기록을 제거한다.
※ burn 메서드 또한 internal이므로 외부에서 직접 호출이 불가하며, 해당 함수를 호출하는 메서드를 추가 구현해야한다. 이때 _burn()을 호출하는 메서드에서 _burn()
메서드 호출 권한을 유동적으로 설정할 수 있을 것으로 예상된다(체크 필요).
실행 후 변경되는 변수
tokenOwner: tokenOwner[_tokenId] = address(0)
ownedTokensCount: ownedTokensCount[_owner]--
ownedTokens: ownedTokens[_owner]에 mapping되는 token array에 _tokenId 제거
ownedTokensIndex: ownedTokens[_owner] mapping되는 token array에 추가된 _tokenId의 인덱스 값 기록 제거
allTokens: 배열에서 토큰(_tokenId) 제거
allTokensIndex: allTokens에 기록된 _tokenId의 index 초기화
26. 4.1 cryptokitties - intro
• 교배 가능한 키티를 사고 파는 게임
• 키티는 각자 고유한 ERC721 토큰에 대응
• 약 40억 개(2^32-1)의 표현형과 유전 형질을 지님
참조: 이더리움 연구회-크립토키티분석
27. https://cryptokittydex.com/kitties/471433
breedWithAuto(uint256 _matronId, uint256 _sireId)
참조: 이더리움 연구회-크립토키티분석
giveBirth(uint256 _matronId)
Cooldowns
새로운 키티를 생성하는 함수(giveBirth)를 직접 호출해야 한다.
giveBirth는 누구나 호출 가능하며, breeding시 지불된 birthFee를
보상으로 받을 수 있다.
* gas fee가 높아지면 운영진이 직접 호출
breedWithAuto를 실행 후 일정 시간이 지나면 새로운 키티를 생성(giveBirth)할 수 있다.
Birth가 일어나는 시점은 breeding Tx가 담기는 블록으로부터 Cooldown / 15sec 번째 블록이다.
교배(breeding)
생성
키티 간(matron, sire) 교배(breeding)를 통해 새로운 키티를 생성한다. 교배를 신청(breedWithAuto)한 후 일정 기간(cooldowns)이 지
나면 새로운 키티를 생성(giveBirth)할 수 있다.
교배 시 성별(sex)을 정할 수 있으며(암컷: matron 수컷: sire), 교배 후 생성된 키티는 matron kitty 보유자가 소유하게 된다.
matron
sire
matron kitty의 소유주가 소유
4.1 cryptokitties - intro
28. 새로이 태어난 키티는 고유한 성질을 지니며(외형, 유전자 등), 또 다른 키티와 교배(Breed)를 하거나, 판매(Sell) 또는 선물(Gift)할 수 있다.
교배(Breed)가 핵심!
4.1 cryptokitties - intro
29. 4.1 Kitty property
참조: https://steemkr.com/kr/@kimyd/3-kittybase
• genes:
키티의 유전자 정보를 표현, 256bit의 genes 값을 토대로 키티의 외형이 결정된다.
• birthtime:
키티가 태어난 날짜(block.timestamp)
• coolDownEndBlock:
키티가 임신했을 경우 새로운 키티가 생성될 수 있는 block number. 현재 블록 넘버(block.number)가 coolDownEndBlock보다 같거나
높아지는 경우 giveBirth 정상 실행된다(kittyBreeding.sol의 _isReadyToGiveBirth 참조).
• matronId:
임신 중인 키티의 ID
• sireId:
씨를 뿌린(아버지) 키티의 ID
• siringWithId:
키티가 임신 중일 경우 matronId를 설정(임신 중이지 않을 경우 0)
• coolDownIndex:
현재 cooldown의 index. 교배 후에 재교배하기까지 어느정도 기다리는지 index에 따라 시간이 결정됨
• generation:
키티의 제네레이션의 수. 부모의 제네레이션의 수에 1를 더한 수(최초의 키티는 0). 여기서 부모 제네레이션 중 높은 값을 토대로 정해진다
(e.g. 아버지 generation= 8, 어머니 generation= 2 인 경우 child generation은 9)
키티는 다양한 속성을 지니므로 구조체(struct)를 이용하여 표현한다. 타입명은 Kitty이다.
* KittyBase.sol에 정의
31. 4.2 크립토키티에서 ERC721이 어떻게 쓰였나? – 시작에 앞서
크립토키티에서 사용된 ERC721 token은 standard가 아닌 draft 버전이다. 크립토키티 게임이 나올 시점(약 2017년 11월)에 ERC721
standard가 정의되어 있지 않았기 때문이다.
contract ERC721 {
// Required methods
function totalSupply() public view returns (uint256 total);
function balanceOf(address _owner) public view returns (uint256 balance);
function ownerOf(uint256 _tokenId) external view returns (address owner);
function approve(address _to, uint256 _tokenId) external;
function transfer(address _to, uint256 _tokenId) external;
function transferFrom(address _from, address _to, uint256 _tokenId) external;
// Events
event Transfer(address from, address to, uint256 tokenId);
event Approval(address owner, address approved, uint256 tokenId);
// Optional
// function name() public view returns (string name);
// function symbol() public view returns (string symbol);
// function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds);
// function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view
returns (string infoUrl);
// ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165)
function supportsInterface(bytes4 _interfaceID) external view returns (bool);
}
<cryptokitties에서 사용된 ERC721>
32. 4.2 크립토키티에서 ERC721이 어떻게 쓰였나? – 주요 변수
/// @dev A mapping from cat IDs to the address that owns them. All cats have
/// some valid owner address, even gen0 cats are created with a non-zero owner.
mapping (uint256 => address) public kittyIndexToOwner;
// @dev A mapping from owner address to count of tokens that address owns.
// Used internally inside balanceOf() to resolve ownership count.
mapping (address => uint256) ownershipTokenCount;
/// @dev A mapping from KittyIDs to an address that has been approved to call
/// transferFrom(). Each Kitty can only have one approved address for transfer
/// at any time. A zero value means no approval is outstanding.
mapping (uint256 => address) public kittyIndexToApproved;
/// @dev A mapping from KittyIDs to an address that has been approved to use
/// this Kitty for siring via breedWith(). Each Kitty can only have one approved
/// address for siring at any time. A zero value means no approval is outstanding.
mapping (uint256 => address) public sireAllowedToAddress;
Kitty[] kitties;
struct Kitty {
uint256 genes;
uint64 birthTime;
uint64 cooldownEndBlock;
uint32 matronId;
uint32 sireId;
uint32 siringWithId;
uint16 cooldownIndex;
uint16 generation;
}
33. 4.2 크립토키티에서 ERC721이 어떻게 쓰였나? – flow
교배(breed)를 통해 키티가 태어나면(birth) kitties 배열에 추가(push)된다. 이때 배열의 index가 ERC721 토큰에서의 고유한 값(tokenId)으로
활용된다.
Kitty[] kitties
32142
…
32143
32144
32145
32146
32147
index
tokenId
1. 교배(breed)
breedWithAuto(uint256 _matronId, uint256 _sireId)
matronId: 32147
sireId: 32146
37. 4.2 크립토키티에서 ERC721이 어떻게 쓰였나? - 정리
Kitty[] kitties
32142
…
32143
32144
32145
32146
32147
0xBb02904FB51b462D8E72a1532279dBb4AE53a365
0x14d591E70c1A63736970e9dEaa8ad1e7DC178B1b
0x14d591E70c1A63736970e9dEaa8ad1e7DC178B1b
0x9108e25f92B70F603Ec4F3a7A1A7AB18ccAe02F5
…
kitty owner(address)
생성되는 키티를 kitties[] 배열에 기록하고, 배열의 index를 tokenId로 활용
각 tokenId 마다 소유주 address가 mapping되며, 이를 통해 tokenId에 해당하는 kitty의 소유 증명(ERC721) 및 거래
38. 4.3 크립토키티 주요 메서드 분석 - breed
function breedWithAuto(uint256 _matronId, uint256 _sireId) external payable whenNotPaused {
// Checks for payment.
require(msg.value >= autoBirthFee);
// Caller must own the matron.
require(_owns(msg.sender, _matronId));
require(_isSiringPermitted(_sireId, _matronId));
// Grab a reference to the potential matron
Kitty storage matron = kitties[_matronId];
// Make sure matron isn't pregnant, or in the middle of a siring cooldown
require(_isReadyToBreed(matron));
// Grab a reference to the potential sire
Kitty storage sire = kitties[_sireId];
// Make sure sire isn't pregnant, or in the middle of a siring cooldown
require(_isReadyToBreed(sire));
// Test that these cats are a valid mating pair.
require(_isValidMatingPair(
matron,
_matronId,
sire,
_sireId
));
// All checks passed, kitty gets pregnant!
_breedWith(_matronId, _sireId);
}
function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) {
address matronOwner = kittyIndexToOwner[_matronId];
address sireOwner = kittyIndexToOwner[_sireId];
// Siring is okay if they have same owner, or if the matron's owner was given
// permission to breed with this sire.
return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner);
}
KittyBreeding.sol
KittyBreeding.sol
function _isReadyToBreed(Kitty _kit) internal view returns (bool) {
// In addition to checking the cooldownEndBlock, we also need to check to see if
// the cat has a pending birth; there can be some period of time between the end
// of the pregnacy timer and the birth event.
return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number));
}
KittyBreeding.sol
function _breedWith(uint256 _matronId, uint256 _sireId) internal {
// Grab a reference to the Kitties from storage.
Kitty storage sire = kitties[_sireId];
Kitty storage matron = kitties[_matronId];
// Mark the matron as pregnant, keeping track of who the sire is.
matron.siringWithId = uint32(_sireId);
// Trigger the cooldown for both parents.
_triggerCooldown(sire);
_triggerCooldown(matron);
// Clear siring permission for both parents. This may not be strictly necessary
// but it's likely to avoid confusion!
delete sireAllowedToAddress[_matronId];
delete sireAllowedToAddress[_sireId];
// Every time a kitty gets pregnant, counter is incremented.
pregnantKitties++;
// Emit the pregnancy event.
Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock);
}
KittyBreeding.sol
39. 4.3 크립토키티 주요 메서드 분석 - Birth
function giveBirth(uint256 _matronId) external whenNotPaused returns(uint256){
// Grab a reference to the matron in storage.
Kitty storage matron = kitties[_matronId];
// Check that the matron is a valid cat.
require(matron.birthTime != 0);
// Check that the matron is pregnant, and that its time has come!
require(_isReadyToGiveBirth(matron));
// Grab a reference to the sire in storage.
uint256 sireId = matron.siringWithId;
Kitty storage sire = kitties[sireId];
// Determine the higher generation number of the two parents
uint16 parentGen = matron.generation;
if (sire.generation > matron.generation) {
parentGen = sire.generation;
}
// Call the sooper-sekret gene mixing operation.
uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1);
// Make the new kitten!
address owner = kittyIndexToOwner[_matronId];
uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner);
// Clear the reference to sire from the matron (REQUIRED! Having siringWithId
// set is what marks a matron as being pregnant.)
delete matron.siringWithId;
// Every time a kitty gives birth counter is decremented.
pregnantKitties--;
// Send the balance fee to the person who made birth happen.
msg.sender.send(autoBirthFee);
// return the new kitten's ID
return kittenId;
}
function _createKitty
(uint256 _matronId, uint256 _sireId, uint256 _generation, uint256 _genes, address
_owner)
internal returns (uint){
~ 코드 생략
Kitty memory _kitty = Kitty({
genes: _genes,
birthTime: uint64(now),
cooldownEndBlock: 0,
matronId: uint32(_matronId),
sireId: uint32(_sireId),
siringWithId: 0,
cooldownIndex: cooldownIndex,
generation: uint16(_generation)
});
//The function returns the new length
//newKittenId = 새로 생성된 kitty가 기록된 배열의 index, 고유한 값이다.
uint256 newKittenId = kitties.push(_kitty) - 1;
require(newKittenId == uint256(uint32(newKittenId)));
// This will assign ownership, and also emit the Transfer event as
// per ERC721 draft
_transfer(0, _owner, newKittenId);
return newKittenId;
}
function _transfer(address _from, address _to, uint256 _tokenId) internal {
// Since the number of kittens is capped to 2^32 we can't overflow this
ownershipTokenCount[_to]++;
// transfer ownership
kittyIndexToOwner[_tokenId] = _to;
// When creating new kittens _from is 0x0, but we can't account that address.
if (_from != address(0)) {
ownershipTokenCount[_from]--;
// once the kitten is transferred also clear sire allowances
delete sireAllowedToAddress[_tokenId];
// clear any previously approved ownership exchange
delete kittyIndexToApproved[_tokenId];
}
Transfer(_from, _to, _tokenId);
}
KittyBreeding.sol
KittyBase.sol
KittyBase.sol
40. 4.3 크립토키티 주요 메서드 분석 - transfer
function transfer(
address _to,
uint256 _tokenId
)
external
whenNotPaused
{
// Safety check to prevent against an unexpected 0x0 default.
require(_to != address(0));
// Disallow transfers to this contract to prevent accidental misuse.
// The contract should never own any kitties (except very briefly
// after a gen0 cat is created and before it goes on auction).
require(_to != address(this));
// Disallow transfers to the auction contracts to prevent accidental
// misuse. Auction contracts should only take ownership of kitties
// through the allow + transferFrom flow.
require(_to != address(saleAuction));
require(_to != address(siringAuction));
// You can only send your own cat.
require(_owns(msg.sender, _tokenId));
// Reassign ownership, clear pending approvals, emit Transfer event.
_transfer(msg.sender, _to, _tokenId);
}
function _transfer(address _from, address _to, uint256 _tokenId) internal {
// Since the number of kittens is capped to 2^32 we can't overflow this
ownershipTokenCount[_to]++;
// transfer ownership
kittyIndexToOwner[_tokenId] = _to;
// When creating new kittens _from is 0x0, but we can't account that address.
if (_from != address(0)) {
ownershipTokenCount[_from]--;
// once the kitten is transferred also clear sire allowances
delete sireAllowedToAddress[_tokenId];
// clear any previously approved ownership exchange
delete kittyIndexToApproved[_tokenId];
}
// Emit the transfer event.
Transfer(_from, _to, _tokenId);
}
function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) {
return kittyIndexToOwner[_tokenId] == _claimant;
}
KittyOwnership.sol
KittyOwnership.sol
KittyBase.sol
* transferFrom 생략
41. 4.3 크립토키티 주요 메서드 분석 - approve
function approve(
address _to,
uint256 _tokenId
)
external
whenNotPaused
{
// Only an owner can grant transfer approval.
require(_owns(msg.sender, _tokenId));
// Register the approval (replacing any previous approval).
_approve(_tokenId, _to);
// Emit approval event.
Approval(msg.sender, _to, _tokenId);
}
function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) {
return kittyIndexToOwner[_tokenId] == _claimant;
}
function _approve(uint256 _tokenId, address _approved) internal {
kittyIndexToApproved[_tokenId] = _approved;
}
KittyOwnership.sol
KittyOwnership.sol
KittyOwnership.sol
42. 참조 자료
eip-ERC721 standard
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
openzeppelin ERC721 implementation
https://github.com/OpenZeppelin/openzeppelin-solidity/tree/master/contracts/token/ERC721
The Anatomy of ERC721
https://medium.com/crypto-currently/the-anatomy-of-erc721-e9db77abfc24
Walking Through the ERC721 Full Implementation
https://medium.com/blockchannel/walking-through-the-erc721-full-implementation-72ad72735f3c
cryptokitties github
https://github.com/cryptocopycats/awesome-cryptokitties/tree/master/contracts
How to Code Your Own CryptoKitties-Style Game on Ethereum
https://medium.com/loom-network/how-to-code-your-own-cryptokitties-style-game-on-ethereum-7c8ac86a4eb3
CryptoKitties Clone In 20 minutes. Non-fungible Token Tutorial
https://maksimivanov.com/posts/gradient-coin-tutorial/#minting
크립토 키티 코드 분석
https://steemkr.com/@kimyd
CryptoKitties Breeding Guide
https://segmentnext.com/2017/12/08/cryptokitties-breeding-guide/