Is there a way pre-deploy a library deployed from within a smart contract before it is deployed? - deployment

Sorry if the question did not make sense. Here is what I am trying to do:
I want to deploy this smart contract (LenseHub) that imports a library that requires data passed to its constructor. This is problematic because I need LenseHub to initialize the contract (a function I can call only after the contract is deployed). If I try to deploy LenseHub without pre-deploying the IERC721Enumerable it will fail obviously. If I can't figure this out I will just inherit IERC721Enumerable and initialize it via the constructor, but would really like to keep the original smart contracts integrity (for testing purposes). Any suggestions on how to do this would be greatly appreciated
Here is the relevant part of the smart contract:
import {IERC721Enumerable} from "#openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
/**
* #title LensHub
* #author Lens Protocol
*
* #notice This is the main entrypoint of the Lens Protocol. It contains governance functionality as well as
* publishing and profile interaction functionality.
*
* NOTE: The Lens Protocol is unique in that frontend operators need to track a potentially overwhelming
* number of NFT contracts and interactions at once. For that reason, we've made two quirky design decisions:
* 1. Both Follow & Collect NFTs invoke an LensHub callback on transfer with the sole purpose of emitting an event.
* 2. Almost every event in the protocol emits the current block timestamp, reducing the need to fetch it manually.
*
* OVERVIEW: The lense protocall is one of the three main solidity contracts compiled. It compiles all of its code imports code into
* one main "hub" from were you can interact with the protocall.
*
*
*/
contract LensHub is
LensNFTBase,
VersionedInitializable,
LensMultiState,
LensHubStorage,
ILensHub
{
uint256 internal constant REVISION = 1;
address internal immutable FOLLOW_NFT_IMPL;
address internal immutable COLLECT_NFT_IMPL;
/**
* #dev This modifier reverts if the caller is not the configured governance address.
*/
modifier onlyGov() {
_validateCallerIsGovernance();
_;
}
/**
* #dev The constructor sets the immutable follow & collect NFT implementations.
*
* #param followNFTImpl The follow NFT implementation address.
* #param collectNFTImpl The collect NFT implementation address.
*/
constructor(address followNFTImpl, address collectNFTImpl) {
if (followNFTImpl == address(0)) revert Errors.InitParamsInvalid();
if (collectNFTImpl == address(0)) revert Errors.InitParamsInvalid();
FOLLOW_NFT_IMPL = followNFTImpl;
COLLECT_NFT_IMPL = collectNFTImpl;
}
/// #inheritdoc ILensHub
function initialize(
string calldata name,
string calldata symbol,
address newGovernance
) external override initializer {
super._initialize(name, symbol);
_setState(DataTypes.ProtocolState.Paused);
_setGovernance(newGovernance);
}
Here is the _function that the initialize function calls:
function _initialize(string calldata name, string calldata symbol) internal {
ERC721Time.__ERC721_Init(name, symbol);
emit Events.BaseInitialized(name, symbol, block.timestamp);
}
Here is the relevent part of the library:
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* #title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* #dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* #dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* #dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* #dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
Here is the constructor of ERC721 that I am trying to pass variables to :
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}

First of all, don't call the IERC721Enumerable a library - it is just an interface you want to implement in your contract. In the context of solidity, a library has a bit different meaning. The question became misleading in the context of solidity.
Secondly, what you want to achieve may be done in two ways - complicated but more correct and easy but less correct:
The complicated approach requires you to use IERC721Upgradeable and properly upgrade your contact when it is needed. I don't think you need to go this far because using a proxy requires a stiff learning curve, and your use case does not require it.
The easier way is to copy the needed interface methods directly inside your contract(or some other class your contact will depend on, that will be open to the needed modifications). This way, you will be able to set your name and symbol whenever you want, and your contract will still be compliant with NFT interface. I know it looks like copying code is a bad idea, but you won't be able to change anything in your contract as soon as it is deployed(if it is not upgradable) thus, copying of the code doesn't matter in the long run.

Related

How can I add autocompletion for Flight PHP microframework in PHPStorm

I've started using Flight microframework, but all methods are hidden under the hood (not declared in the Flight class).
How can I configure PHPStorm or should I write new set of rules?
Update: use framework instance doesn't work
I've tried to use framework instance, but has no success — I have internal methods in the suggestion list:
Update: autocomplete implemented in the Flight framework
First of all: I'd suggest to submit new issue on their Issue Tracker asking to provide some sort of helper file (like below).. or implement it in any other way (e.g. via PHPDoc' #method for Flight class -- no helper needed and no changes in the actual code -- just PHPDoc) so that IDE (e.g. PhpStorm or Netbeans) would not complain for non-existing methods and you will have some code completion help from IDE.
Magic is good .. but not when whole interface is based on such magic.
On the actual question, which you can resolve yourself.
You will have to spend some time (half an hour or even less) and create some fake Flight class and put it anywhere in your IDE -- it will be used for code completion only. Yes, IDE may warn you about duplicate classes.. but that inspection can be turned off.
The idea is to create a class and declare all required methods as they should have been done if it would be an ordinary class. To start with (will resolve issues for first code example on their readme):
<?php
class Flight
{
/**
* Routes a URL to a callback function.
*
* #param string $pattern URL pattern to match
* #param callback $callback Callback function
* #param boolean $pass_route Pass the matching route object to the callback
*/
public static function route($pattern, $callback, $pass_route = false) {}
/**
* Starts the framework.
*/
public static function start() {}
}
Here is how it looks now:
As you can see Flight is underwaved -- IDE says that there is more than one class with such name in this project. Just tell PhpStorm to not to report such cases:
For adding methods to the original class via #method PHPDoc tags:
/**
* Bla-bla -- class description
*
* #method static void route(string $pattern, callback $callback, bool $pass_route = false) Routes a URL to a callback function
* #method static void start() Starts the framework
*/
class Flight
{
...
}

GWT / JSNI - "DataCloneError - An object could not be cloned" - how do I debug?

I am attempting to call out to parallels.js via JSNI. Parallels provides a nice API around web workers, and I wrote some lightweight wrapper code which provides a more convenient interface to workers from GWT than Elemental. However I'm getting an error which has me stumped:
com.google.gwt.core.client.JavaScriptException: (DataCloneError) #io.mywrapper.workers.Parallel::runParallel([Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JavaScriptObject;)([Java object: [Ljava.lang.String;#1922352522, JavaScript object(3006), JavaScript object(3008)]): An object could not be cloned.
This comes from, in hosted mode:
at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:249) at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136) at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:571) at com.google.gwt.dev.shell.ModuleSpace.invokeNativeVoid(ModuleSpace.java:299) at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeVoid(JavaScriptHost.java:107) at io.mywrapper.workers.Parallel.runParallel(Parallel.java)
Here's my code:
Example client call to create a worker:
Workers.spawnWorker(new String[]{"hello"}, new Worker() {
#Override
public String[] work(String[] data) {
return data;
}
#Override
public void done(String[] data) {
int i = data.length;
}
});
The API that provides a general interface:
public class Workers {
public static void spawnWorker(String[] data, Worker worker) {
Parallel.runParallel(data, workFunction(worker), callbackFunction(worker));
}
/**
* Create a reference to the work function.
*/
public static native JavaScriptObject workFunction(Worker worker) /*-{
return worker == null ? null : $entry(function(x) {
worker.#io.mywrapper.workers.Worker::work([Ljava/lang/String;)(x);
});
}-*/;
/**
* Create a reference to the done function.
*/
public static native JavaScriptObject callbackFunction(Worker worker) /*-{
return worker == null ? null : $entry(function(x) {
worker.#io.mywrapper.workers.Worker::done([Ljava/lang/String;)(x);
});
}-*/;
}
Worker:
public interface Worker extends Serializable {
/**
* Called to perform the work.
* #param data
* #return
*/
public String[] work(String[] data);
/**
* Called with the result of the work.
* #param data
*/
public void done(String[] data);
}
And finally the Parallels wrapper:
public class Parallel {
/**
* #param data Data to be passed to the function
* #param work Function to perform the work, given the data
* #param callback Function to be called with result
* #return
*/
public static native void runParallel(String[] data, JavaScriptObject work, JavaScriptObject callback) /*-{
var p = new $wnd.Parallel(data);
p.spawn(work).then(callback);
}-*/;
}
What's causing this?
The JSNI docs say, regarding arrays:
opaque value that can only be passed back into Java code
This is quite terse, but ultimately my arrays are passed back into Java code, so I assume these are OK.
EDIT - ok, bad assumption. The arrays, despite only ostensibly being passed back to Java code, are causing the error (which is strange, because there's very little googleability on DataCloneError.) Changing them to String works; however, String isn't sufficient for my needs here. Looks like objects face the same kinds of issues as arrays do; I saw Thomas' reference to JSArrayUtils in another StackOverflow thread, but I can't figure out how to call it with an array of strings (it wants an array of JavaScriptObjects as input for non-primitive types, which does me no good.) Is there a neat way out of this?
EDIT 2 - Changed to use JSArrayString wherever I was using String[]. New issue; no stacktrace this time, but in the console I get the error: Uncaught ReferenceError: __gwt_makeJavaInvoke is not defined. When I click on the url to the generated script in developer tools, I get this snippet:
self.onmessage = function(e) {self.postMessage((function (){
try {
return __gwt_makeJavaInvoke(3)(null, 65626, jsFunction, this, arguments);
}
catch (e) {
throw e;
}
})(e.data))}
I see that _gwt_makeJavaInvoke is part of the JSNI class; so why would it not be found?
You can find working example of GWT and WebWorkers here: https://github.com/tomekziel/gwtwwlinker/
This is a preliminary work, but using this pattern I was able to pass GWT objects to and from webworker using serialization provided by AutoBeanFactory.
If you never use dev mode it is currently safe to pretend that a Java String[] is a JS array with strings in it. This will break in dev mode since arrays have to be usable in Java and Strings are treated specially, and may break in the future if the compiler optimizes arrays differently.
Cases where this could go wrong in the future:
The semantics of Java arrays and JavaScript arrays are different - Java arrays cannot be resized, and are initialized with specific values based on the component type (the data in the array). Since you are writing Java code, the compiler could conceivable make assumptions based on details about how you create and use that array that could be broken by JS code that doesn't know to never modify the array.
Some arrays of primitive types could be optimized into TypedArrays in JavaScript, more closely following Java semantics in terms of resizing and Java behavior in terms of allocation. This would be a performance boost as well, but could break any use of int[], double[], etc.
Instead, you should copy your data into a JsArrayString, or just use the js array to hold the data rather than going back and forth, depending on your use case. The various JsArray types can be resized and already exist as JavaScript objects that outside JS can understand and work with.
Reply to EDIT 2:
At a guess, the parallel.js script is trying to run your code from another scope such a in the webworker (that's the point of the code, right) where your GWT code isn't present. As such, it can't call the makeJavaInvoke which is the bridge back into dev mode (would be a different failure with compiled JS). According to http://adambom.github.io/parallel.js/ there are specific requirements that a passed callback must meet to be passed in to spawn and perhaps then - your anonymous functions definitely do not meet them, and it may not be possible to maintain java semantics.
Before I get much deeper, check out this answer I did a while ago addressing the basic issues with webworkers and gwt/java: https://stackoverflow.com/a/11376059/860630
As noted there, WebWorkers are effectively new processes, with no shared code or shared state with the original process. The Parallel.js code attempts to paper over this with a little bit of trickery - shared state is only available in the form of the contents passed in to the original Parallel constructor, but you are attempting to pass in instances of 'java' objects and calling methods on them. Those Java instances come with their own state, and potentially can link back to the rest of the Java app by fields in the Worker instance. If I were implementing Worker and doing something that referenced other data than what was passed in, then I would be seeing further bizarre failures.
So the functions you pass in must be completely standalone - they must not refer to external code in any way, since then the function can't be passed off to the webworker, or to several webworkers, each unaware of each other's existence. See https://github.com/adambom/parallel.js/issues/32 for example:
That's not possible since it would
require a shared state across workers
require us to transmit all scope variables (I don't think there's even a possibility to read the available scopes)
The only thing which might be possible would be cache variables, but these can already be defined in the function itself with spawn() and don't make any sense in map (because there's no shared state).
Without being actually familiar with how parallel.js is implemented (all of this answer so far is reading the docs and a quick google search for "parallel.js shared state", plus having experiemented with WebWorkers for a day or so and deciding that my present problem wasn't yet worth the bother), I would guess that then is unrestricted, and you can you pass it whatever you like, but spawn, map, and reduce must be written in such a way that their JS can be passed off to the new JS process and completely stand alone there.
This may be possible from your normal Java code when compiled, provided you have just one implementation of Worker and that impl never uses state other than what is directly passed in. In that case the compiler should rewrite your methods to be static so that they are safe to use in this context. However, that doesn't make for a very useful library, as it seems you are trying to achieve. With that in mind, you could keep your worker code in JSNI to ensure that you follow the parallel.js rules.
Finally, and against the normal GWT rules, avoid $entry for calls you expect to happen in other contexts, since those workers have no access to the normal exception handling and scheduling that $entry enables.
(and finally finally, this is probably still possible if you are very careful at writing Worker implementations and write a Generator that invokes each worker implementation in very specific ways to make sure that com.google.gwt.dev.jjs.impl.MakeCallsStatic and com.google.gwt.dev.jjs.impl.Pruner can correctly act to knock out the this in those instance methods once they've been rewritten as JS functions. I think the cleanest way to do this is to emit the JSNI in the generator itself, call a static method written in real Java, and from that static method call the specific instance method that does the heavy lifting for spawn, etc.)

Is there a way to annotate an AutoBean property so that it will not be serialized/deserialized?

I have an autobean with a property that is only needed for the UI. I believe that you can null out values and the AutoBeanCodex will not serialized that property, but that equates to an extra step which is needed at serialization.
I was hoping for some annotation similar to the Editor #Ignore annotation. For example:
public interface Foo {
...
#Ignore
String getUiOnlyProperty();
}
So, other than nulling out the value at serialization time, is there any other way to keep an autobean property from being serialized?
Autobeans are meant to be a Java skin on a JSON/XML/whatever format - they aren't really designed to hold other pieces of data. That said, several thoughts that either nearly answer your question with out-of-the-box tools, or might inspire some other ideas on how to solve your problem.
You should be able to build read-only properties by omitting the setter. This isn't quite what you are asking for, but still might be handy.
Along those lines, the JavaDoc for the #PropertyName annotation seems to allude to this possible feature:
/**
* An annotation that allows inferred property names to be overridden.
* <p>
* This annotation is asymmetric, applying it to a getter will not affect the
* setter. The asymmetry allows existing users of an interface to read old
* {#link AutoBeanCodex} messages, but write new ones.
*/
Reading old messages but writing new ones seems like it might be closer to what you are after, and still allowing you to work with the thing-that-looks-like-a-bean.
The real answer though seems to be the AutoBean.setTag and getTag methods:
/**
* A tag is an arbitrary piece of external metadata to be associated with the
* wrapped value.
*
* #param tagName the tag name
* #param value the wrapped value
* #see #getTag(String)
*/
void setTag(String tagName, Object value);
...
/**
* Retrieve a tag value that was previously provided to
* {#link #setTag(String, Object)}.
*
* #param tagName the tag name
* #return the tag value
* #see #setTag(String, Object)
*/
<Q> Q getTag(String tagName);
As can be seen from the implementation of these methods in AbstractAutoBean, these store their data in a totally separate object from what is sent over the wire. The downside is that you'll need to get the underlying AutoBean object (see com.google.web.bindery.autobean.shared.AutoBeanUtils.getAutoBean(U) for one way to do this) in order to invoke these methods.
child class/interface decoded as a parent interface does not explode on decoding allowing the goods to be passed together before the marshalling steps. my immediate test of the actual code below is performing as expected.
public interface ReplicateOptions {
/**
* Create target database if it does not exist. Only for server replications.
*/
Boolean getCreateTarget();
void setCreateTarget(Boolean create_target);
//baggage to pass along
interface ReplicateCall<T> extends ReplicateOptions {
/**
* If true starts subscribing to future changes in the source database and continue replicating them.
*/
AsyncCallback<T> getContinuous();
void setContinuous(AsyncCallback<T> continuous);
}
}

What are the scopes of GIN bindings?

I wonder what scopes folowing two bindings have:
bind(PermissionManager.class).in(Singleton.class);
and
bind(PermissionManager.class);
I have read the JavaDocs, they are as following. For Singleton:
/**
* Apply this to implementation classes when you want only one instance
* (per {#link Injector}) to be reused for all injections for that binding.
*
* #author crazybob#google.com (Bob Lee)
*/
For no scope:
/**
* No scope; the same as not applying any scope at all. Each time the
* Injector obtains an instance of an object with "no scope", it injects this
* instance then immediately forgets it. When the next request for the same
* binding arrives it will need to obtain the instance over again.
*
* <p>This exists only in case a class has been annotated with a scope
* annotation such as {#link Singleton #Singleton}, and you need to override
* this to "no scope" in your binding.
*
* #since 2.0
*/
What does this mean in practical terms? Are singletons per client or per JVM? For no scope, is every instance different?
In practical terms for Gin, the Singleton scope makes the most sense when considered per client instance, or even more accurately, per Ginjector instance. If you make the mistake of making two Ginjectors by GWT.createing an instance twice, you likely will have one 'singleton' per instance, since each Ginjector can only keep track of the instances it manages.
So each time your application loads, it will have its own singleton. If the user opens the same application twice in two different tabs, each will have its own singleton. You could consider each tab to be its own JVM, as it will have its own copy of all of the classes, and won't be able communicate, or call methods* on the other window.
For no scope, yes, by default each instance is different. When a type is #Injected, it will be a new instance there, but if you #Inject a Provider for a field, every time you call get() you can get a fresh instance. This can be helpful to get several newly injected instances easily.
Singletons make sense to use in two main cases
When the instance holds shared state that needs to be common across many injections - the most common case.
When the instance is expensive to create - on the server this is often done as a pool, so no more than X objects are created, but the expensive objects on the client tend to be views, with lots of widgets, and generally more than one is not required.
* It is possible to call methods on another window, but you need to use the browser's capabilities for this, by posting a message, not by just passing an object back and forth.
Singletons are only created once by the top level Ginjector that you create (and for most applications, you only ever create one Ginjector).
Unscoped objects are created every time they are injected as a dependency into another object. So every instance will be different. You actually don't need to write bind(SomeClass.class) if you are not going to scope it (or do any of the other things that the binder DSL can let you do to a binding). Simply having the default constructor or adding #Inject to a constructor will let Gin be able to create it.
Generally, when you are using Guice or Gin you want to leave things unscoped unless you have a good reason not to. I would recommend reading over the Guice documentation about scopes.

What is the phpdoc syntax to link $this to a specific class in Aptana?

I'm working on Magento templates, but this issue would apply to any template loading system.
As these templates are loaded by the template engine there's no way for the IDE (in this case Aptana) to know what object type $this is.
Potentially it could more than one object as a single template could be loaded by multiple objects, but ignoring this, what would the correct phpdoc syntax be to specify a specific class for the $this object?
You can define it like this:
/* #var $this type */
where type is a class name
To be clear, using $this should only ever indicate an object of the current class, right?
PhpDocumentor doesn't currently (v1.4.3) recognize $this as a specific keyword that should equate to a datatype of the class itself.
Only datatypes known by PHP and classes already parsed by PhpDocumentor are the proper datatype values to use with the #return tag. There is a feature request in to have some option available in PhpDocumtentor to aid in documenting fluent methods that always "return $this". [1]
In the case of the #var tag, I don't see how it would be feasible for a class variable to contain its own class instance. As such, I can't follow what "#var $this" should be saying.
If, however, your intention with $this is not for fluent methods that "return $this", and was simply to be some shortcut to PhpDocumentor and/or your IDE to magically guess what datatypes you might mean by using $this, I'd have to guess there's no way to do it. The closest suggestion I could make would be to use the name of a parent class that is a common parent to all the various child classes that this particular var/return might be at runtime, and then use the description part of the tag to have inline {#link} tags that list out the possible child classes that are possible.
Example: I have a Parent abstract class with Child1, Child2, and Child3 children that each could occur in my runtime Foo class.
So, Foo::_var could be any of those child class types at runtime, but how would I document this?
/**
* #var Parent this could be any child of {#link Parent}, {#link Child1}, {#link Child2}, or {#link Child3}...
*/
protected $_var;
Getting back to the "return $this" issue, I'd document things in a similar way:
/**
* a fluent method (i.e. it returns this class's instance object)
* #return Parent this could be any child of {#link Parent}, {#link Child1}, {#link Child2}, or {#link Child3}...
*/
public function foo() {
return $this;
}
Documenting this way at least allows your class doc to have links to the particular classes. What it fails to do is highlight the fluent 'ness. However, if your IDE is capable of recognizing the class names, then perhaps it will be able to do the necessary logical linking to those other classes. I think Eclipse is able to do this at least with popup help, if you hover over the class name in the tag's description. I do not think Eclipse can use this to then make the various child classes' methods available in code completion. It would know about the Parent methods for code completion, because the datatype I explicitly list is Parent, but that's as far as the IDE can go.
[1] -- http://pear.php.net/bugs/bug.php?id=16223
I have found that defining a type with #var for $this does not work - presumably because $this is special and is treated as such by Aptana. I have a similar need to the poster I think - it is in template files (in my case simply located and included by functions within the data class) that I wish to set a type for $this. As #ashnazg says, setting a type for $this within a class definition is not needed, because the type of $this is always the type of the class (up to inheritance).
There is, however, a workaround for template files. At the top of the template file simply put something like
/**
* #var My_Data_Model_Type
*/
$dataModel = &$this;
Then simply use $dataModel (or whatever you choose to call it - maybe something shorter) instead of $this in the template