- Azimuth: https://github.com/urbit/azimuth/blob/master/contracts/Azimuth.sol
- Ecliptic: https://github.com/urbit/azimuth/blob/master/contracts/Ecliptic.sol
Operators of an address are allowed to transfer ownership of all points owned by their associated address (ERC721’s approveAll()). A transfer proxy is allowed to transfer ownership of a single point (ERC721’s approve()).
Azimuth
// Azimuth is just the data store. Ecliptic is the logic contract.
// In this way, Azimuth/Ecliptic is 'upgradeable' - you can
// swap out Ecliptic in order to change the logic, without
// compromising the Azimuth data store
// Events elided
// the actual azimuth Point
struct Point {
bytes32 encrptionKey; // encyrption pub key
bytes32 authenticationKey; // auth pub key
uint32[] spawned; // children
bool hasSponsor; // sponsor IS supporting
bool active; // can be "linked" (no belong to prefix)
bool escapeRequested; // in pending sponsor-change state
uint32 sponsor; // curernt supporter or last (if hasSponsor false)
uint32 escapeRequestedTo; // the new req'd sponsor
unit32 cryptoSuiteVersion; / pubkey suite version
uint32 keyRevisionNumber; // incremented when pubkey changed
unit32 continuityNumber; // incremented on network breach
}
// permisions for a point. aka 'rights'
struct Deed {
address owner; // eth address owning point
address managementProxy; // 0 or eth address
address spawnProxy; // 0 or addr who can spawn children
address votingProxy; // 0 or addr with voting rights
address transferProxy; // 0 or addr who can transfer this point
}
// state
//
// uint32 is the point. these are "per point"
mapping(uint32 => Point) public points;
mapping(uint32 => Deed) public rights;
// owner => address. has right to transfer _all_ the owner's points
mapping(address => mapping(address => bool)) public operators;
// base domains for contacting galaxies. Deeply centralized!
string[3] public dnsDomains; // [0] is primary, others are fallbacks
//
// end state
// lookups
//
// per point, who they are sponsoring
mapping(uint32 => uint32[]) public sponsoring;
// gives indexes (index + 1) for the above.
mapping(uint32 => mapping(uint32 => uint256)) public sponsoringIndexes;
// per point, the other points it has escape requests from
mapping(uint32 => uint32[]) public escapeRequests;
// indexes for above
mapping(uint32 => mapping(uint32 => uint256)) public escapeRequestsIndexes;
// points owned by this address
mapping(address => uint32[]) public pointsOwnedBy;
// indexes for above (also used for deleting owners)
mapping(address => mapping(uint32 => uint256)) public pointOwnerIndexes;
// the following four also have indexes, elided here.
//
// per address, points they management proxy for
mapping(address => uint32[]) public managerFor;
// per address, points they can spawn with
mapping(address => uint32[]) public spawningFor;
// per address, points they can vote with
mapping(address => uint32[]) public votingFor;
// per address, points they can transfer
mapping(address => uint32[]) public transferringFor;
//
// end lookups
// logic
//
// eliding anything that isn't directly related to Husk, for now
// Deed-reading:
// returns owner of _point
function getOwner(uint32 _point)
view
external
returns (address owned)
{
return rights[_point].owner;
}
// true if _point is owned by _address
function isOwner(uint32 _point, address _address)
// similar to above:
function getManagementProxy(uint32 _point)
function isManagementProxy(uint32 _point, address _address)
returns (bool result)
// similar, but includes owner and management proxy:
function canManage(uint32 _point, address _who)
// returns all points a proxy address can manage
function getManagerFor(address _proxy)
returns (uint32[] mfor)
// similar to above for transfers:
// point's current transfer proxy
function getTransferProxy(uint32 _point)
returns (address transferProxy)
function isTransferProxy(uint32 _point, address _address)
returns (bool result)
// true for owner, transfer proxy or "operator" of point's current owner
function canTransfer(uint32 _point, address _who)
returns (bool result)
// returns all points proxy can transfer
function getTransferringFor(address _proxy)
returns (uint32[] tfor)
// true if operator is allowed to txfr ownership of _owner's points
function isOperator(address _owner, address _operator)
returns (bool result)
// Deed-Writing **important for Husk**
// See ecliptic
// set owner of _point to _owner
function setOwner(uint32 _point, address _owner)
onlyOwner // of contract, aka Ecliptic
// See ecliptic
// makes _proxy the _point's management proxy
function setManagementProxy(uint32 _point, address _proxy)
// See ecliptic
// makes _proxy the _point's transfer proxy
function setTransferProxy(uint32 _point, address _proxy)
Ecliptic
// The logic contract / owner for Azimuth.
// Azimuth data store doesn't change, but the way you interact
// with it can change by swapping out / upgrading Ecliptic.
// This contract implements the ERC721 interface for non-fungible tokens,
// allowing points to be managed using generic clients that support the
// standard. It also implements ERC165 to allow this to be discovered.
// Events elided
// get the current owner of point _tokenId
//
function ownerOf(uint256 _tokenId)
returns (address owner)
// transfer point _tokenID from _from to _to
function safeTransferFrom(address _from, address _to, uint256 _tokenID)
// transfer point _tokenID from _from to _to
// AND CALL CONTRACT -- Husk!
function safeTransferFrom(address _from, address _to, uint256 _tokenID bytes _data)
// transfer point _tokenId from _from to _to,
// WITHOUT notifying recipient contract
//
function transferFrom(address _from, address _to, uint256 _tokenId)
// transfer _point to _target, clearing all permissions
// data and keys if _reset is true
//
// Requirements:
// - :msg.sender must be either _point's current owner, authorized
// to transfer _point, or authorized to transfer the current
// owner's points (as in ERC721's operator)
//
function transferPoint(uint32 _point, address _target, bool _reset)
// internally calls azimuth.canTransfer(_point, msg.sender))
// that is: current owner or operator for current owner OR txfr proxy
// internally calls azimuth.setOwner(_point, _target)
Questions / Confusions
-
What is a “prefix”?
-
// getPrefix(): compute prefix ("parent") of _point - so the “prefix” is the “parent”
- What is “parent”?
-
-
need more clarity on “operator”
- These are apparently part of the ERC721 standard.
Questions for Husk
- will red horizon be using the “operator of an address” or its transfer proxy?
-
how do I use “callbacks” - idea being to use the safeTranferFrom and include the husk contract to tell husk that a husk-style transfer just happened.
- but does this “safeTransfer” imply the recipient must accept? that won’t work for Husk.
- this seems to be part of the ERC721 standard. Look into