-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Integrate Commonwealth chain events. (#108)
* Add CWP contracts. * Stub out CWP changes. * Initial complete implementation for CW Protocol. * Export commonwealth types. * Fix createApi call. * Fix subscriber and update solidity. * Bug fixing for protocol. * Fix paths.
- Loading branch information
Showing
31 changed files
with
5,910 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
//////////////////////////////////////////////////////////////////////////////////////////// | ||
/// @title DataTypes | ||
//////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
// this order of variables optimizes gas by using the least amount of 32 byte storage spaces as possible | ||
library DataTypes { | ||
struct ProjectMetaData { | ||
uint256 id; | ||
bytes32 name; | ||
bytes32 ipfsHash; | ||
bytes32 url; | ||
address creator; | ||
} | ||
|
||
struct ProtocolData { | ||
uint8 fee; | ||
address payable feeTo; | ||
} | ||
|
||
struct ProjectData { | ||
uint256 threshold; | ||
uint256 deadline; // uint24 max val = 6.9 years | ||
address payable beneficiary; | ||
address acceptedToken; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "./IProjectBase.sol"; | ||
|
||
interface ICuratedProject is IProjectBase { | ||
event Curate(address sender, address token, uint256 amount); | ||
|
||
function bToken() external view returns (address); | ||
|
||
function cToken() external view returns (address); | ||
|
||
function totalCuratorFunding() external view returns (address); | ||
|
||
function curatorFee() external view returns (address); | ||
|
||
function initialize( | ||
DataTypes.ProjectMetaData memory _metaData, | ||
DataTypes.ProjectData memory _projectData, | ||
DataTypes.ProtocolData memory _protocolData, | ||
uint256 _curatorFee, | ||
address _bToken, | ||
address _cToken | ||
) external returns (bool); | ||
|
||
function curate(uint256 _amount) external returns (bool); | ||
|
||
function curatorsWithdraw() external returns (bool); | ||
|
||
function withdrawRemaining() external view returns (uint256); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "./IProjectBaseFactory.sol"; | ||
|
||
interface ICuratedProjectFactory is IProjectBaseFactory { | ||
function setPTokenImpl(address _pToken) external; | ||
|
||
function createProject( | ||
bytes32 _name, | ||
bytes32 _ipfsHash, | ||
bytes32 _url, | ||
address payable _beneficiary, | ||
address _acceptedToken, | ||
uint256 _threshold, | ||
uint256 _deadline, | ||
uint256 _curatorFee | ||
) external returns (address); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {DataTypes} from './DataTypes.sol'; | ||
|
||
interface IProjectBase { | ||
event Back(address sender, address token, uint256 amount); | ||
event Withdraw(address sender, address token, uint256 amount, bytes32 withdrawalType); | ||
event Succeeded(uint256 timestamp, uint256 amount); | ||
event Failed(); | ||
|
||
/////////////////////////////////////////// | ||
// Getters - view functions | ||
////////////////////////////////////////// | ||
function metaData() external view returns (DataTypes.ProjectMetaData memory); | ||
|
||
function threshold() external view returns (uint256); // backing threshold in native token | ||
|
||
function deadline() external view returns (uint256); // deadline in blocktime | ||
|
||
function totalFunding() external view returns (uint256); | ||
|
||
function protocolFee() external view returns (uint256); | ||
|
||
function protocolFeeTo() external view returns (address); | ||
|
||
function acceptedToken() external view returns (address); | ||
|
||
function beneficiary() external view returns (address); | ||
|
||
function lockedWithdraw() external view returns (bool); | ||
|
||
function funded() external view returns (bool); | ||
|
||
/////////////////////////////////////////// | ||
// functions | ||
////////////////////////////////////////// | ||
|
||
function setName(bytes32 _name) external; | ||
|
||
function setIpfsHash(bytes32 _ipfsHash) external; | ||
|
||
function back(uint256 _amount) external returns (bool); | ||
|
||
function beneficiaryWithdraw() external returns (bool); | ||
|
||
function backersWithdraw() external returns (bool); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import './DataTypes.sol'; | ||
|
||
interface IProjectBaseFactory { | ||
event ProjectCreated(uint256 projectIndex, address newProject); | ||
|
||
function protocolData() external view returns (DataTypes.ProtocolData memory); | ||
|
||
function owner() external view returns (address); | ||
|
||
function projectImp() external view returns (address); | ||
|
||
function projects(uint32 projectIndex) external view returns (address); | ||
|
||
function isAcceptedToken(address token) external view returns (bool); | ||
|
||
function numProjects() external view returns (uint256); | ||
|
||
function addAcceptedTokens(address[] memory _tokens) external; | ||
|
||
function setFeeTo(address payable _feeTo) external; | ||
|
||
function setProtocolFee(uint256 _protocolFee) external; | ||
|
||
function setProjectImpl(address _projectImpl) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import { Listener as BaseListener } from '../../Listener'; | ||
import { | ||
CWEvent, | ||
IDisconnectedRange, | ||
SupportedNetwork, | ||
} from '../../interfaces'; | ||
import { addPrefix, factory } from '../../logging'; | ||
|
||
import { | ||
Api, | ||
EventKind, | ||
IEventData, | ||
ListenerOptions as CommonwealthListenerOptions, | ||
RawEvent, | ||
} from './types'; | ||
import { createApi } from './subscribeFunc'; | ||
import { Subscriber } from './subscriber'; | ||
import { Processor } from './processor'; | ||
import { StorageFetcher } from './storageFetcher'; | ||
|
||
export class Listener extends BaseListener< | ||
Api, | ||
StorageFetcher, | ||
Processor, | ||
Subscriber, | ||
EventKind | ||
> { | ||
public discoverReconnectRange: (chain: string) => Promise<IDisconnectedRange>; | ||
|
||
private readonly _options: CommonwealthListenerOptions; | ||
|
||
protected readonly log; | ||
|
||
constructor( | ||
chain: string, | ||
contractAddress: string, | ||
url?: string, | ||
skipCatchup?: boolean, | ||
verbose?: boolean, | ||
discoverReconnectRange?: (c: string) => Promise<IDisconnectedRange> | ||
) { | ||
super(SupportedNetwork.Commonwealth, chain, verbose); | ||
|
||
this.log = factory.getLogger( | ||
addPrefix(__filename, [SupportedNetwork.Commonwealth, this._chain]) | ||
); | ||
|
||
this._options = { | ||
url, | ||
contractAddress, | ||
skipCatchup: !!skipCatchup, | ||
}; | ||
|
||
this.discoverReconnectRange = discoverReconnectRange; | ||
|
||
this._subscribed = false; | ||
} | ||
|
||
public async init(): Promise<void> { | ||
try { | ||
this._api = await createApi( | ||
this._options.url, | ||
this._options.contractAddress, | ||
10 * 1000, | ||
this._chain | ||
); | ||
} catch (error) { | ||
this.log.error(`Fatal error occurred while starting the API`); | ||
throw error; | ||
} | ||
|
||
try { | ||
this._processor = new Processor(this._api, this._chain); | ||
this._subscriber = new Subscriber(this._api, this._chain, this._verbose); | ||
this.storageFetcher = new StorageFetcher(this._api, this._chain); | ||
} catch (error) { | ||
this.log.error( | ||
`Fatal error occurred while starting the Processor, StorageFetcher and Subscriber` | ||
); | ||
throw error; | ||
} | ||
} | ||
|
||
public async subscribe(): Promise<void> { | ||
if (!this._subscriber) { | ||
this.log.info( | ||
`Subscriber for ${this._chain} isn't initialized. Please run init() first!` | ||
); | ||
return; | ||
} | ||
|
||
if (!this.options.skipCatchup) await this.processMissedBlocks(); | ||
else this.log.info(`Skipping event catchup!`); | ||
|
||
try { | ||
this.log.info( | ||
`Subscribing to Commonwealth factory contract: ${this._chain}, on url ${this._options.url}` | ||
); | ||
await this._subscriber.subscribe(this.processBlock.bind(this)); | ||
this._subscribed = true; | ||
} catch (error) { | ||
this.log.error(`Subscription error: ${error.message}`); | ||
} | ||
} | ||
|
||
public async updateAddress(): Promise<void> { | ||
// TODO | ||
} | ||
|
||
private async processMissedBlocks(): Promise<void> { | ||
this.log.info(`Detected offline time, polling missed blocks...`); | ||
|
||
if (!this.discoverReconnectRange) { | ||
this.log.info( | ||
`Unable to determine offline range - No discoverReconnectRange function given` | ||
); | ||
} | ||
|
||
let offlineRange: IDisconnectedRange; | ||
try { | ||
offlineRange = await this.discoverReconnectRange(this._chain); | ||
if (!offlineRange) { | ||
this.log.warn(`No offline range found, skipping event catchup.`); | ||
return; | ||
} | ||
} catch (error) { | ||
this.log.error( | ||
`Could not discover offline range: ${error.message}. Skipping event catchup.` | ||
); | ||
return; | ||
} | ||
|
||
if (!offlineRange || !offlineRange.startBlock) { | ||
this.log.warn(`Unable to determine offline time range.`); | ||
return; | ||
} | ||
|
||
try { | ||
const cwEvents = await this.storageFetcher.fetch(offlineRange); | ||
for (const event of cwEvents) { | ||
await this.handleEvent(event); | ||
} | ||
} catch (error) { | ||
this.log.error(`Unable to fetch events from storage: ${error.message}`); | ||
} | ||
} | ||
|
||
protected async processBlock(event: RawEvent): Promise<void> { | ||
const { blockNumber } = event; | ||
if (!this._lastBlockNumber || blockNumber > this._lastBlockNumber) { | ||
this._lastBlockNumber = blockNumber; | ||
} | ||
|
||
const cwEvents: CWEvent[] = await this._processor.process(event); | ||
|
||
for (const evt of cwEvents) { | ||
await this.handleEvent(evt as CWEvent<IEventData>); | ||
} | ||
} | ||
|
||
public get options(): CommonwealthListenerOptions { | ||
return this._options; | ||
} | ||
} |
Oops, something went wrong.